Aop入口,以及加载流程、源码

2,027 阅读8分钟
原文链接: github.com

Spring-Core核心官网

概念(摘自-翻译官网)

aop对于面向对象是一种通过另外一种编程架构的思想的补充,面向对象关键的模块就是类,
然而对于aop来说最重要的关键模块是切面,
切面使得多内容和多对象的关系能够模块化(比如事务管理)
Spring AOP框架就是一种实现,AOP(Spring)通过可靠的中间件解决方案对IoC进行补充

AOP框架中的一些术语(概念)

Aspect: 将不同类之间的关系进行了模块化,
在Springboot 中直接定义注解 @Aspect 就可以声明一个切面类

Join point:(织入点)程序执行的一个点,在Spring-AOP中通常代表一个方法的执行;

Advice:执行计划,具体切面在一个具体的执行点的执行计划(可以是方法前,方法后,异常情况触发等等)
Pointcut:满足织入点条件的断言,就是aop的范围
Introduction:
Target object:在Spring中就是原生的定义的bean
(因为bean加载过程中会通过代理生成新的bean然后在新的bean中定义一个targetObject对象,指向原生的bean)
Aop proxy:aop的代理对象
Weaving

Spring AOP中的一些概念(织入方式)
Before advice
After returning advice
After throwing advice
After (finally) advice
Around advice

源码入口:

Spring-boot

org.springframework.boot:spring-boot-autoconfigure 包中

AopAutoConfiguration.class类中
找到 @EnableAspectJAutoProxy 注解
定义了:
@Import(AspectJAutoProxyRegistrar.class)


class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		
        //这里初始化了aop的类
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}

}

------
顺着代码点进去发现最后初始化了一个bean:
AnnotationAwareAspectJAutoProxyCreator.class


普通Spring

spring-aop jar包
META-INF 包的 Resource Bundle 'spring' 包
spring.handlers 文件
AopNamespaceHandler.class 类,用来解析aop 标签
点进解析类中,调用的还是 AopConfigUtils.java 的解析方法,注册aop启动类

AnnotationAwareAspectJAutoProxyCreator.class

AbstractAutoProxyCreator.java 解析

AnnotationAwareAspectJAutoProxyCreator.java 就是继承自这个类(通过多个父类)

关键点

AbstractAutoProxyCreator.java 
实现了 SmartInstantiationAwareBeanPostProcessor.class
(BeanPostProcessor.java 子类) 接口


BeanPostProcessor.java

这个类的加载时机是在bean实例化之后调用,然后把postProcessAfterInitialization()方法返回值返回,取代原先的bean,所以一般实现了这个接口的类,需要把bean返回,Spring中BeanPostProcessor.java按照order的顺序排序的,aop的排在最后面,保证bean都能进入aop代理
public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

Tips:

BeanPostProcessor.java 不感应(其他)BeanPostProcessor.java 的加载

AbstractAutoProxyCreator.java 的 postProcessAfterInitialization()方法



@Override
   public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
   	Object cacheKey = getCacheKey(beanClass, beanName);

   	if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
   		if (this.advisedBeans.containsKey(cacheKey)) {
   			return null;
   		}
   		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
   			this.advisedBeans.put(cacheKey, Boolean.FALSE);
   			return null;
   		}
   	}

   	// Create proxy here if we have a custom TargetSource.
   	// Suppresses unnecessary default instantiation of the target bean:
   	// The TargetSource will handle target instances in a custom fashion.
   	if (beanName != null) {
   	      //获取系统配置的targetSource生成工厂类,这里可以配置热交换的入口,然而springboot中还没有入口
   		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
   		if (targetSource != null) {
   			this.targetSourcedBeans.add(beanName);
   			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
   			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
   			this.proxyTypes.put(cacheKey, proxy.getClass());
   			return proxy;
   		}
   	}

   	return null;
   }


   /**
    * Create a proxy with the configured interceptors if the bean is
    * identified as one to proxy by the subclass.
    * @see #getAdvicesAndAdvisorsForBean
    */
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   	if (bean != null) {
   		Object cacheKey = getCacheKey(bean.getClass(), beanName);
   		if (!this.earlyProxyReferences.contains(cacheKey)) {
   			return wrapIfNecessary(bean, beanName, cacheKey);
   		}
   	}
   	return bean;
   }
   
   
   
   /**
    * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
    * @param bean the raw bean instance
    * @param beanName the name of the bean
    * @param cacheKey the cache key for metadata access
    * @return a proxy wrapping the bean, or the raw bean instance as-is
    */
   protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   	if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
   		return bean;
   	}
   	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
   		return bean;
   	}
   	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
   		this.advisedBeans.put(cacheKey, Boolean.FALSE);
   		return bean;
   	}

   	// Create proxy if we have advice.
   	//加载切面策略
   	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   	if (specificInterceptors != DO_NOT_PROXY) {
   		this.advisedBeans.put(cacheKey, Boolean.TRUE);
   		//代理生成新的代理bean
   		Object proxy = createProxy(
   				bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
   		this.proxyTypes.put(cacheKey, proxy.getClass());
   		return proxy;
   	}

   	this.advisedBeans.put(cacheKey, Boolean.FALSE);
   	return bean;
   }



   /**
    * Create an AOP proxy for the given bean.
    * @param beanClass the class of the bean
    * @param beanName the name of the bean
    * @param specificInterceptors the set of interceptors that is
    * specific to this bean (may be empty, but not null)
    * @param targetSource the TargetSource for the proxy,
    * already pre-configured to access the bean
    * @return the AOP proxy for the bean
    * @see #buildAdvisors
    */
   protected Object createProxy(
   		Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

   	if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
   		AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
   	}
   	//代理工厂类
   	ProxyFactory proxyFactory = new ProxyFactory();
   	proxyFactory.copyFrom(this);
   	//这里判断代理方式,默认是jdk代理,但是当类是类或者指定了target-class=true,就只能使用cglib(asm)代理
   	if (!proxyFactory.isProxyTargetClass()) {
   		if (shouldProxyTargetClass(beanClass, beanName)) {
   			proxyFactory.setProxyTargetClass(true);
   		}
   		else {
   			evaluateProxyInterfaces(beanClass, proxyFactory);
   		}
   	}
   	//生成代理策略类
   	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   	proxyFactory.addAdvisors(advisors);
   	//targetSource就是原生的bean对象
   	proxyFactory.setTargetSource(targetSource);
   	customizeProxyFactory(proxyFactory);

   	proxyFactory.setFrozen(this.freezeProxy);
   	if (advisorsPreFiltered()) {
   		proxyFactory.setPreFiltered(true);
   	}
   	//代理生成新的bean
   	return proxyFactory.getProxy(getProxyClassLoader());
   }

ProxyFactory.java 代理工厂代码

	/**
    * Create a new proxy according to the settings in this factory.
    * <p>Can be called repeatedly. Effect will vary if we've added
    * or removed interfaces. Can add and remove interceptors.
    * <p>Uses a default class loader: Usually, the thread context class loader
    * (if necessary for proxy creation).
    * @return the proxy object
    */
   public Object getProxy() {
   	return createAopProxy().getProxy();
   }

AopProxy.java

 
 public interface AopProxy {

	/**
	 * Create a new proxy object.
	 * <p>Uses the AopProxy's default class loader (if necessary for proxy creation):
	 * usually, the thread context class loader.
	 * @return the new proxy object (never {@code null})
	 * @see Thread#getContextClassLoader()
	 */
	Object getProxy();

	/**
	 * Create a new proxy object.
	 * <p>Uses the given class loader (if necessary for proxy creation).
	 * {@code null} will simply be passed down and thus lead to the low-level
	 * proxy facility's default, which is usually different from the default chosen
	 * by the AopProxy implementation's {@link #getProxy()} method.
	 * @param classLoader the class loader to create the proxy with
	 * (or {@code null} for the low-level proxy facility's default)
	 * @return the new proxy object (never {@code null})
	 */
	Object getProxy(ClassLoader classLoader);

}

重点看 CglibAopProxy.java 代码

动态代理实现的核心类
先说说普通的动态代理
Enhancer实现步骤:
1.设置superclass -> 需要代理的类
2.设置callback类 -> 代理类,实现MethodInterceptor.java接口的
3.enhancer.create() 生成代理类

代码(加注释):


class CglibAopProxy implements AopProxy, Serializable {


	@Override
	public Object getProxy(ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
		}

		try {
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			if (ClassUtils.isCglibProxyClass(rootClass)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			//设置superclass ,代理类
			enhancer.setSuperclass(proxySuperClass);
			//实现接口advised ,所以我们最后运行的程序中的bean都是 Advised 接口的实现类(这个类有特殊的用法)
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
			//callback,aop的主要类 DynamicAdvisedInterceptor.java 
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			//创建代理类实例,enhancer.create()
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of class [" +
					this.advised.getTargetClass() + "]: " +
					"Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of class [" +
					this.advised.getTargetClass() + "]: " +
					"Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}


	......省略部分代码

	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimization choices...
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// Choose an "aop" interceptor (used for AOP calls).
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

		// Choose a "straight to target" interceptor. (used for calls that are
		// unadvised but can return this). May be required to expose the proxy.
		Callback targetInterceptor;
		if (exposeProxy) {
			targetInterceptor = isStatic ?
					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
		}
		else {
			targetInterceptor = isStatic ?
					new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
		}

		// Choose a "direct to target" dispatcher (used for
		// unadvised calls to static targets that cannot return this).
		Callback targetDispatcher = isStatic ?
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();

		Callback[] mainCallbacks = new Callback[] {
				aopInterceptor,  // for normal advice
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};

		Callback[] callbacks;

		// If the target is a static one and the advice chain is frozen,
		// then we can make some optimizations by sending the AOP calls
		// direct to the target using the fixed chain for that method.
		if (isStatic && isFrozen) {
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);

			// TODO: small memory optimization here (can skip creation for methods with no advice)
			for (int x = 0; x < methods.length; x++) {
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
				fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
						chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
				this.fixedInterceptorMap.put(methods[x].toString(), x);
			}

			// Now copy both the callbacks from mainCallbacks
			// and fixedCallbacks into the callbacks array.
			callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
			System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
			System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
			this.fixedInterceptorOffset = mainCallbacks.length;
		}
		else {
			callbacks = mainCallbacks;
		}
		return callbacks;
	}

	....省略部分代码


}

DynamicAdvisedInterceptor.java 拦截类


	/**
	 * General purpose AOP callback. Used when the target is dynamic or when the
	 * proxy is not frozen.
	 * 代码实现很简单
	 * 熟悉 cglib动态代理的实现的一看就知道了
	 * 
	 	aop实现步骤
	 	先定义interceptor
	 	把原来封装的advisor 、targetSource 封装到advised中
	 	当调用bean.dosomething()时

	 	其实是

	 	interceptor.intercept()的调用
	 		-.类校验
	 		-.AopContext设值
	 		-.先获取advisor调用链,并调用
	 		-.bean原生方法调用
	 		-.advisor调用链,并调用
	 		-.AopContext设值

	 *
	 */
	private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

		private final AdvisedSupport advised;

		public DynamicAdvisedInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}

		@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Class<?> targetClass = null;
			Object target = null;
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// May be null. Get as late as possible to minimize the time we
				// "own" the target, in case it comes from a pool...
				target = getTarget();
				if (target != null) {
					targetClass = target.getClass();
				}
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null) {
					releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

		@Override
		public boolean equals(Object other) {
			return (this == other ||
					(other instanceof DynamicAdvisedInterceptor &&
							this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
		}

		/**
		 * CGLIB uses this to drive proxy creation.
		 */
		@Override
		public int hashCode() {
			return this.advised.hashCode();
		}

		protected Object getTarget() throws Exception {
			return this.advised.getTargetSource().getTarget();
		}

		protected void releaseTarget(Object target) throws Exception {
			this.advised.getTargetSource().releaseTarget(target);
		}
	}



AopContext.java 有特殊的用途,在bean中调用自己,如果需要aop管理,不能通过this.dosomething()调用,可以通过 AopContext获取到当前bean对象

最后

其实aop设计的源码挺简单,spring的事务管理,几乎和这个差不多