前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【小家Spring】Spring AOP的核心类:AbstractAdvisorAutoProxy自动代理创建器深度剖析(AnnotationAwareAspectJAutoProxyCreator)

【小家Spring】Spring AOP的核心类:AbstractAdvisorAutoProxy自动代理创建器深度剖析(AnnotationAwareAspectJAutoProxyCreator)

作者头像
YourBatman
发布2019-09-03 16:21:09
2.6K0
发布2019-09-03 16:21:09
举报
文章被收录于专栏:BAT的乌托邦BAT的乌托邦

前言

上篇博文:

【小家Spring】面向切面编程之—Spring AOP的原理讲解以及源码分析(Cannot find current proxy: Set ‘exposeProxy’ property on )

已经刚刚结合实例,介绍了Spring AOP的过程以及对源码进行了逐步分析~

但是这中间当时事忽略了整个Spring AOP最为核心的一个类:自动代理创建器

本文将主要以AnnotationAwareAspectJAutoProxyCreator为引线,好好聊聊自动代理创建器是做什么的,具体做了什么,以及Spring为我们提供的其它几个Creator:DefaultAdvisorAutoProxyCreatorInfrastructureAdvisorAutoProxyCreatorAspectJAwareAdvisorAutoProxyCreator,有何区别和对应的实用场景

可以看出来,所有的创建器都是AbstractAutoProxyCreator该抽象类的子类~

当系统比较复杂,或者中需要进行aop进行织入的bean较多时,简单采用ProxyFacotryBean无疑会增加很多工作量(因为每个Bean都得手动写一个)。另外由于要从ProxyFactoryBean获得代理对象,也会使应用和Spring之间的耦合度增加,并且很多时候可维护性不强(我个人认为耦合这个不是最主要的原因,毕竟现在Spring已成为实际上的规范了)。

譬如,我们需要给bean名字满足“*service”的bean每个方法增加事务功能,如果采用ProxyFacotryBean必须为每个以service结尾的bean增加一个配置(工作量巨大),若需要修改,这个后果是灾难性的。

这样的情况下,自动代理的方式就能发挥它巨大的优势了,牛刀小试一把,上面案例只需下面一个类就搞定了(这里以功能最弱的BeanNameAutoProxyCreator为例):

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  <property name="beanNames"><value>*service</value></property>
  <property name="interceptorNames">
    <list>
      <!-- 这里可以写具体的Interceptor的BeanName -->
      <value>myInterceptor</value>
    </list>
  </property>
</bean>
Spring中自动创建代理器(分类)

在内部,Spring使用BeanPostProcessor让自动生成代理。基于BeanPostProcessor的自动代理创建器的实现类,将根据一些规则在容器实例化Bean时为匹配的Bean生成代理实例。代理创建器可以分为三类:

  1. 基于Bean配置名规则的自动代理生成器:允许为一组特定配置名的Bean自动创建代理实例的代理创建器,实现类为BeanNameAutoProxyCreator
  2. 基于Advisor匹配机制的自动代理创建器它会对容器中的所有Advisor进行扫描,自动将这些切面应用到匹配的Bean中,实现类是DefaultAdvisorAutoProxyCreator(它也支持前缀匹配)
  3. 基于Bean中AspectJ注解的自动代理生成器:为包含AspectJ注解的切入的Bean自动创建代理实例

AbstractAutoProxyCreator
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
		...
}

首先它继承自:ProxyProcessorSupport这个类应该很熟了,我们之前介绍过的三大创建代理对象的工厂**ProxyFactoryBean、ProxyFactory、AspectJProxyFactory**都是继承自此类的

参考:【小家Spring】面向切面编程Spring AOP创建代理的方式:ProxyFactoryBean、ProxyFactory、AspectJProxyFactory(JDK Proxy和CGLIB)

这里还是简单的科普一下吧:

// 显然,它是个ProxyConfig 拥有AOP的基本配置
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {
	...
	// 这是它最重要的一个方法:就是把该bean所有的实现的接口 都作用在ProxyFactory 上 当然是有过滤得
	protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
		// 拿到该类所有实现的接口们~~~~
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());

		// 标记:是否存在“有问题的”代理接口  默认是false
		boolean hasReasonableProxyInterface = false;
		for (Class<?> ifc : targetInterfaces) {
			
			//判断这些接口是否是“有问题的”:既我们需要处理的
			if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
					ifc.getMethods().length > 0) {
				hasReasonableProxyInterface = true;
				break;
			}
		}
		
		// 说明除开哪些接口外,但凡有一个有用的接口,就add进去(这样就会采用JDK的动态代理了)
		if (hasReasonableProxyInterface) {
			for (Class<?> ifc : targetInterfaces) {
				proxyFactory.addInterface(ifc);
			}
		}
		// 否则直接采用CGLIB
		else {
			proxyFactory.setProxyTargetClass(true);
		}
	}
	// InitializingBean...Aware接口的子接口等等这些回调性质的接口
	protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
		return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
				AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
	}
	// 接口名称为这些的  也就是spring aop自己的东西
	protected boolean isInternalLanguageInterface(Class<?> ifc) {
		return (ifc.getName().equals("groovy.lang.GroovyObject") ||
				ifc.getName().endsWith(".cglib.proxy.Factory") ||
				ifc.getName().endsWith(".bytebuddy.MockAccess"));
	}
	
}

AbstractAutoProxyCreator是对自动代理创建器的一个抽象实现。最重要的是,它实现了SmartInstantiationAwareBeanPostProcessor接口,因此会介入到Spring IoC容器Bean实例化的过程,因此由此为入口进行展开~

SmartInstantiationAwareBeanPostProcessor继承自InstantiationAwareBeanPostProcessor继承自BeanPostProcessor 所以它需要实现的方法有很多~~~ 这里重点提一个方法(如下图):在bean被crate之前,先会执行所有的InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation,谁第一个返回了不为null的Bean,后面就都不会执行了 。然后会再执行BeanPostProcessor#postProcessAfterInitialization 就完事了

按照执行顺序,我们来看看AbstractAutoProxyCreator的实现:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
	
	// 实现类就是我们熟悉的它:	DefaultAdvisorAdapterRegistry
	private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();	

	// 目标源的创建器。它有一个方法getTargetSource(Class<?> beanClass, String beanName)
	// 两个实现类:QuickTargetSourceCreator和LazyInitTargetSourceCreator
	// 它的具体使用 后面有详解
	@Nullable
	private TargetSourceCreator[] customTargetSourceCreators;
	@Nullable
	private BeanFactory beanFactory;
	...
	private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
	private final Set<Object> earlyProxyReferences = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
	private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
	private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
	...
	
	// 可以自己指定Registry 
	public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
		this.advisorAdapterRegistry = advisorAdapterRegistry;
	}
	// 可议指定多个
	public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {
		this.customTargetSourceCreators = targetSourceCreators;
	}
	// 通用拦截器得名字。These must be bean names in the current factory
	// 这些Bean必须在当前容器内存在的~~~
	public void setInterceptorNames(String... interceptorNames) {
		this.interceptorNames = interceptorNames;
	}
	//Set whether the common interceptors should be applied before bean-specific ones
	// 默认值是true
	public void setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst) {
		this.applyCommonInterceptorsFirst = applyCommonInterceptorsFirst;
	}

	//===========下面是关于BeanPostProcessor的一些实现方法============
	
	// getBeanNamesForType()的时候会根据每个BeanName去匹配类型合适的Bean,这里不例外,也会帮忙在proxyTypes找一下
	@Override
	@Nullable
	public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
		if (this.proxyTypes.isEmpty()) {
			return null;
		}
		Object cacheKey = getCacheKey(beanClass, beanName);
		return this.proxyTypes.get(cacheKey);
	}

	// getEarlyBeanReference()它是为了解决单例bean之间的循环依赖问题,提前将代理对象暴露出去
	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			this.earlyProxyReferences.add(cacheKey);
		}
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

	// 不做构造函数检测,返回null 让用空构造初始化吧
	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}
	
	// 这个很重要,在Bean实例化之前,先给一个机会,看看缓存里有木有,有就直接返回得了
	// 简单的说:其主要目的在于如果用户使用了自定义的TargetSource对象,则直接使用该对象生成目标对象,而不会使用Spring的默认逻辑生成目标对象
	// (并且这里会判断各个切面逻辑是否可以应用到当前bean上)
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);
		
		// beanName无效或者targetSourcedBeans里不包含此Bean
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			
			//advisedBeans:已经被通知了的(被代理了的)Bean~~~~  如果在这里面  也返回null 
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			// isInfrastructureClass:Advice、Pointcut、Advisor、AopInfrastructureBean的子类,表示是框架所属的Bean
			// shouldSkip:默认都是返回false的。AspectJAwareAdvisorAutoProxyCreator重写此方法:只要存在一个Advisor   ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)成立  就返回true
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {	
				// 所以这里会把我们所有的Advice、Pointcut、Advisor、AopInfrastructureBean等Bean都装进来
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		//到这,只有在TargetSource中没有进行缓存,并且应该被切面逻辑环绕,但是目前还未生成代理对象的bean才会通过此方法

		// Create proxy here if we have a custom TargetSource.
		// 如果我们有TargetSourceCreator,这里就会创建一个代理对象
		// getCustomTargetSource逻辑:存在TargetSourceCreator  并且 beanFactory.containsBean(beanName)  然后遍历所有的TargetSourceCreator,调用getTargetSource谁先创建不为null就终止
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		// 若创建好了这个代理对象,继续进一步的操作:::
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
			  	// 缓存起来
				this.targetSourcedBeans.add(beanName);
			}
			
			//getAdvicesAndAdvisorsForBean:方法判断当前bean是否需要进行代理,若需要则返回满足条件的Advice或者Advisor集合
			// 这个方法由子类实现,AbstractAdvisorAutoProxyCreator和BeanNameAutoProxyCreator  代表中两种不同的代理方式
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			
			// 顾名思义,就是根据目标对象创建代理对象的核心逻辑了 下面详解
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			
			// 把创建好的代理  缓存~~~
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}

	// 这个方法也很重要,若我们自己要实现一个TargetSourceCreator ,就可议实现我们自定义的逻辑了
	// 这里条件苛刻:customTargetSourceCreators 必须不为null
	// 并且容器内还必须有这个Bean:beanFactory.containsBean(beanName)    备注:此BeanName指的即将需要被代理得BeanName,而不是TargetSourceCreator 的BeanName
	//下面会介绍我们自己自定义一个TargetSourceCreator 来实现我们自己的逻辑
	@Nullable
	protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
		// We can't create fancy target sources for directly registered singletons.
		if (this.customTargetSourceCreators != null &&
				this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
			for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
				TargetSource ts = tsc.getTargetSource(beanClass, beanName);
				if (ts != null) {
					// Found a matching TargetSource.
					if (logger.isDebugEnabled()) {
						logger.debug("TargetSourceCreator [" + tsc +
								" found custom TargetSource for bean with name '" + beanName + "'");
					}
					return ts;
				}
			}
		}

		// No custom TargetSource found.
		return null;
	}

	// 这三个方法,没做什么动作~~
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) {
		return true;
	}
	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
		return pvs;
	}
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}


	// 代理是通过AbstractAutoProxyCreator中的postProcessAfterInitialization()创建的
	// 因此这个方法是蛮重要的,主要是wrapIfNecessary()方法会特别的重要
	// earlyProxyReferences缓存:该缓存用于保存已经创建过代理对象的cachekey,**避免重复创建**
	@Override
	public Object postProcessAfterInitialization(@Nullable 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;
	}

	// ============wrapIfNecessary方法==============
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 若此Bean已经在targetSourcedBeans里,说明已经被代理过,那就直接返回即可
		// (postProcessBeforeInstantiation()中成功创建的代理对象都会将beanName加入到targetSourceBeans中)
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		
		// 如果该Bean基础框架Bean或者免代理得Bean,那也不处理
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 逻辑同上,对于实现了Advice,Advisor,AopInfrastructureBean接口的bean,都认为是spring aop的基础框架类,不能对他们创建代理对象,
		// 同时子类也可以覆盖shouldSkip方法来指定不对哪些bean进行代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		// getAdvicesAndAdvisorsForBean该方法由子类实现,如国有Advice切面切进去了,我们就要给他代理
		//根据getAdvicesAndAdvisorsForBean()方法的具体实现的不同,AbstractAutoProxyCreator又分成了两类自动代理机制
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		
		// 需要代理,那就进来给它创建一个代理对象吧
		if (specificInterceptors != DO_NOT_PROXY) {
			// 缓存起来,赋值为true,说明此key是被代理了的
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			
			// 创建这个代理对象
			Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			// 创建好后缓存起来  避免重复创建
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}
		
		// 不需要代理,也把这种不需要代理的对象给与缓存起来  赋值为false
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	// 创建代理对象  specificInterceptors:作用在这个Bean上的增强器们
	// 这里需要注意的地方:入参是targetSource  而不是target
	// 所以最终代理的是  ``每次AOP代理处理方法调用时,目标实例都会用到TargetSource实现``
	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}
		
		// 这个我们非常熟悉了ProxyFactory   创建代理对象的三大方式之一~~~
		ProxyFactory proxyFactory = new ProxyFactory();
		// 复制当前类的相关配置,因为当前类它也是个ProxyConfig
		proxyFactory.copyFrom(this);

		// 看看是否是基于类的代理(CGLIB),若表面上是基于接口的代理  我们还需要进一步去检测
		if (!proxyFactory.isProxyTargetClass()) {
			// shouldProxyTargetClass方法用于判断是否应该使用targetClass类而不是接口来进行代理
			// 默认实现为和该bean定义是否属性值preserveTargetClass为true有关。默认情况下都不会有此属性值的~~~~~
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			
			// 到此处,上面说了,就是把这个类实现的接口们,都放进proxyFactory(当然也会处理一些特殊的接口~~~不算数的)
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		
		// buildAdvisors:整理合并得到最终的advisors (毕竟interceptorNames还指定了一些拦截器的)
		// 至于调用的先后顺序,通过applyCommonInterceptorsFirst参数可以进行设置,若applyCommonInterceptorsFirst为true,interceptorNames属性指定的Advisor优先调用。默认为true
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		// 添加进工厂里
		proxyFactory.addAdvisors(advisors);
		// 把targetSource放进去  TargetSource的实现方式有多种 后面会介绍
		proxyFactory.setTargetSource(targetSource);

		// 这个方法是交给子类的,子类可以继续去定制此proxyFactory(Spring内部并没有搭理它)
		customizeProxyFactory(proxyFactory);
		
		// 沿用this得freezeProxy的属性值
		proxyFactory.setFrozen(this.freezeProxy);
		
		// 设置preFiltered的属性值,默认是false。子类:AbstractAdvisorAutoProxyCreator修改为true
		// preFiltered:字段意思为:是否已为特定目标类筛选Advisor
		// 这个字段和DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice获取所有的Advisor有关
		//CglibAopProxy和JdkDynamicAopProxy都会调用此方法,然后递归执行所有的Advisor的
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
		
		// getProxyClassLoader():调用者可议指定  否则为:ClassUtils.getDefaultClassLoader()
		return proxyFactory.getProxy(getProxyClassLoader());
	}

	// 下面,只剩一个重要的方法:buildAdvisors()没有解释了
	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// 解析interceptorNames而来得Advisor数组~~~
		Advisor[] commonInterceptors = resolveInterceptorNames();

		// 注意:此处用得事Object
		List<Object> allInterceptors = new ArrayList<>();

		if (specificInterceptors != null) {
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
				
			// 若解析它来的有内容
			if (commonInterceptors.length > 0) {
				// 放在头部  也就是最上面
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				// 放在末尾
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}

		// 把每一个Advisor都用advisorAdapterRegistry.wrap()包装一下~~~~
		// 注意wrap方法,默认只支持那三种类型的Advice转换为Advisor的~~~
		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

	// 处理interceptorNames,去容器内找出来
	private Advisor[] resolveInterceptorNames() {
		BeanFactory bf = this.beanFactory;
		ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
		List<Advisor> advisors = new ArrayList<>();
		for (String beanName : this.interceptorNames) {
			// 排除一些情况:此工厂不是ConfigurableBeanFactory或者该Bean不在创建中
			if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
				Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
				
				// 拿到这个Bean,然后使用advisorAdapterRegistry把它适配一下即可~~~
				Object next = bf.getBean(beanName);
				advisors.add(this.advisorAdapterRegistry.wrap(next));
			}
		}
		return advisors.toArray(new Advisor[0]);
	}

}

关于TargetSource以及TargetSourceCreator 的使用,以及为何使用它们?这里我推荐想了解原因的,请参照这里:

为什么需要TargetSource

Spring Aop之Target Source详解

这两篇文章我看了讲得还是不错的,能到到扫盲的目的~

我们当然可以自定义TargetSource,一般我们就这么用,使用ProxyFactoryBean去指定配置某个Bean,而不是用自动代理创建器(它会使用默认的TargetSource,当然你可以重写它的)

<!-- 这个我们也可以自己实现,也可以用Spring为我们提供好的 -->
<bean id="poolTargetSource"    
    class="org.springframework.aop.target.CommonsPoolTargetSource">  
    <property name="targetBeanName"><value>businessObject</value></property>  
    <property name="maxSize"><value>25</value></property>  
</bean>  
 
<!-- 让具体的Bean代理,去使用我们自己指定的targetSource(一般只有非单例的需要自己去实现) -->
<bean id="businessObject"   class="org.springframework.aop.framework.ProxyFactoryBean">  
    <property name="targetSource"><ref local="poolTargetSource"/></property>  
    <property name="interceptorNames"><value>myInterceptor</value></property>  
</bean>  

但是有时候我们希望参与到自动代理层面去,使用我们自己的targetSource,其实我们可以这么做,自己实现一个TargetSourceCreator:(原理:AbstractAutoProxyCreator#getCustomTargetSource()

绝大多数情况下调用者不会自己去实现TargetSourceCreator,而是Spring采用默认的SingletonTargetSource去生产AOP对象 LazyInitTargetSource在JMX的MBean中使用较为广泛,所以是右边要了解的

// 它是根据BeanName强相关的,所以现在和Spring容器是强关联的
@FunctionalInterface
public interface TargetSourceCreator {
	@Nullable
	TargetSource getTargetSource(Class<?> beanClass, String beanName);

}

从Spring自带的实现中可议看出,都是和Spring容器相关的实现。LazyInitTargetSourceCreator:和@Lazy属性有关(LazyInitTargetSource)。QuickTargetSourceCreator:可能来自CommonsPool2TargetSource、可能来自ThreadLocalTargetSource、可能来自PrototypeTargetSource(和BeanName有关),可能是null。

public class QuickTargetSourceCreator extends AbstractBeanFactoryBasedTargetSourceCreator {

	// 可以看出,它的分类事根据BeanName以xxx开头来分辨的~~~这是一种约束
	public static final String PREFIX_COMMONS_POOL = ":";
	public static final String PREFIX_THREAD_LOCAL = "%";
	public static final String PREFIX_PROTOTYPE = "!";

	@Override
	@Nullable
	protected final AbstractBeanFactoryBasedTargetSource createBeanFactoryBasedTargetSource(
			Class<?> beanClass, String beanName) {

		if (beanName.startsWith(PREFIX_COMMONS_POOL)) {
			CommonsPool2TargetSource cpts = new CommonsPool2TargetSource();
			cpts.setMaxSize(25);
			return cpts;
		}
		else if (beanName.startsWith(PREFIX_THREAD_LOCAL)) {
			return new ThreadLocalTargetSource();
		}
		else if (beanName.startsWith(PREFIX_PROTOTYPE)) {
			return new PrototypeTargetSource();
		}
		else {
			// No match. Don't create a custom target source.
			return null;
		}
	}

}

然后我们要想自定义一个,还是比较麻烦的,可议这么干~

@Order(Ordered.HIGHEST_PRECEDENCE) //我们希望自己定义的Bean最先被加载  所以这里优先级调到最高了 覆盖@EnableAspectJAutoProxy它自动导入的Bean
@Configuration
public class RootConfig {

    // 这里需要考虑到的是Spring对配置文件的加载顺序(@Import的解析顺序),我们必须在@EnableAspectJAutoProxy这个注解之前生效才有效
    // 同一个Configuration内解析顺序为:Process any @ComponentScan annotations ...  Process any @Import annotations  ... Process individual @Bean methods
    // 所以问题就在这里:如果我们把`@EnableAspectJAutoProxy`注解下载@Component这种Lite配置上,肯定会被先扫描进行的  所以这里:我极力不推荐这么做,而是放在Configuration正规的配置文件里
    // 然后又因为同一个@Import早于@Bean之前执行,所以我们必须放在不同的@Configaration文件内,然后通过控制配置类的顺序来达到目的~~~~(它支持@Order进行排序)

    // 参考链接:https://blog.csdn.net/f641385712/article/details/88554592 和  参考方法ConfigurationClassPostProcessor#processConfigBeanDefinitions

    @Bean(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME) //Bean名称务必只能是这个
    public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
        AnnotationAwareAspectJAutoProxyCreator creator = new AnnotationAwareAspectJAutoProxyCreator();
        // creator.setProxyTargetClass(true); 建议这里不要设置,还是取用注解的值来灵活控制最好了

        // 手动指定进去一个TargetSourceCreator(责任链模式:我们可以指定多个 ... )
        creator.setCustomTargetSourceCreators(new LazyInitTargetSourceCreator());
        return creator;
    }
}

@Order(Ordered.LOWEST_PRECEDENCE)
@EnableAspectJAutoProxy
@Configuration
public class AopConfig {

}

显示是比较麻烦的,而且涉及到了很多的Spring解析@Configuration底层原理东西,一般不建议这么弄吧~


AbstractAutoProxyCreator的创建步骤就是上面源码分析的,它就相当于一个代理创建的模版,规定了一些步骤。获取Advisor的getAdvicesAndAdvisorsForBean由各子类自己去实现~~~

接下来主要是根据对方法getAdvicesAndAdvisorsForBean()的实现不一样,策略也就有两种了。它有两个直接实现:BeanNameAutoProxyCreatorAbstractAdvisorAutoProxyCreator

BeanNameAutoProxyCreator

顾名思义,它和Advisor无关,只和BeanName有关(只有名字匹配上了,都会给创建一个代理类)

所以我认为它是个半自动的,哪些需要创建代理,还需要我们自己指定(虽然支持*通配符)

从这篇博文:

【小家Spring】面向切面编程之—Spring AOP的原理讲解以及源码分析(Cannot find current proxy: Set ‘exposeProxy’ property on )

我们已经能知道,若我们使用@EnableAspectJAutoProxy启动自动代理的话,Spring自动会给我们注册一个Bean:AnnotationAwareAspectJAutoProxyCreator,它是一个AbstractAdvisorAutoProxyCreator,和AspectJ注解相关~

本文我们要Demo一下BeanNameAutoProxyCreator,很简单以这样做就可以了:

    @Bean
    public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
        BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
        // 给所有以serviceImpl结尾的类创建代理对象(支持正则)  备注:aliases也是被支持的
        // 注意此处若只写`*Service` 是匹配不上helloServiceImpl
        beanNameAutoProxyCreator.setBeanNames("*ServiceImpl");

        // 备注:它要想使用拦截,只能通过setInterceptorNames,从容器内拿Advice的实现类(自己书写)
        beanNameAutoProxyCreator.setInterceptorNames("myMethodInteceptor");
        return beanNameAutoProxyCreator;
    }

就这样配置,MyMethodInteceptor这个拦截器,它就会作用于拦截所有的*ServiceImpl上。

备注:此时我们采用了BeanNameAutoProxyCreator自然就不用再@EnableAspectJAutoProxy,自然@Aspect切面也就不生效了。 当然,也可以开启的,这样他俩就联合生效了(但不太建议去这么使用

需要注意的是:如果一个对象被切多次(比如使用@Async、事务都会创建代理对象),最终这个对象代理可能是对层的:如下所示:

另外,如果你想用自己注册的@Bean代替@EnableAspectJAutoProxy默认给你注册的自动创建器,那么你可以注册一个Bean名称如下的Bean即可:

// 手动注册一个自动代理创建器,且名字务必叫AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME
@Bean(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME) 
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
	...
}

特别提醒:首先我强烈不建议这么去做 然后,此处要注意Bean定义信息的加载循序,否则也是不会生效的(需要对原理更多的了解吧) 毕竟人家判断是根据Bean的定义信息来判断的:if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {} 而这个就和@Configuration配置文件的加载顺序有关喽(Spring环境下不好控制~)

BeanNameAutoProxyCreator源码一览:

//@since 10.10.2003  可以看出这个类出现得非常早
public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
	@Nullable
	private List<String> beanNames;

	public void setBeanNames(String... beanNames) {
		Assert.notEmpty(beanNames, "'beanNames' must not be empty");
		this.beanNames = new ArrayList<>(beanNames.length);
		for (String mappedName : beanNames) {
			// 对mappedName做取出空白处理
			this.beanNames.add(StringUtils.trimWhitespace(mappedName));
		}
	}
	// simpleMatch并不是完整的正则。但是支持*这种通配符,其余的不支持哦
	protected boolean isMatch(String beanName, String mappedName) {
		return PatternMatchUtils.simpleMatch(mappedName, beanName);
	}


	// 这里面注意一点:BeanNameAutoProxyCreator的此方法并没有去寻找Advisor,所以需要拦截的话
	// 只能依靠:setInterceptorNames()来指定拦截器。它是根据名字去Bean容器里取的
	@Override
	@Nullable
	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

		if (this.beanNames != null) {
			for (String mappedName : this.beanNames) {
				// 显然这里面,如果你针对的是FactoryBean,也是兼容的~~~
				if (FactoryBean.class.isAssignableFrom(beanClass)) {
					if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
						continue;
					}
					// 对BeanName进行处理,去除掉第一个字符
					mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
				}
				
				// 匹配就返回PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS 而不是再返回null了
				if (isMatch(beanName, mappedName)) {
					return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
				}
				
				// 这里需要注意的是,如国存在Bean工厂,哪怕任意一个alias匹配都是可以的~~~
				BeanFactory beanFactory = getBeanFactory();
				if (beanFactory != null) {
					String[] aliases = beanFactory.getAliases(beanName);
					for (String alias : aliases) {
						if (isMatch(alias, mappedName)) {
							return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
						}
					}
				}
			}
		}
		return DO_NOT_PROXY;
	}
}

AbstractAdvisorAutoProxyCreator 这是另一类自动代理方式

它是Spring2.0提供的(2.0版本2006年才发布哦~~~)

顾名思义,它和**Advisor**有关(只有被切入的类,才会给它创建一个代理类),它的核心方法是实现了父类的:getAdvicesAndAdvisorsForBean来获取Advisor

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {

	// 这个类是重点,后面会详细介绍
	@Nullable
	private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;

	// 重写了setBeanFactory方法,事需要保证bean工厂必须是ConfigurableListableBeanFactory
	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		super.setBeanFactory(beanFactory);
		if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
			throw new IllegalArgumentException(
					"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
		}
		// 就这一句话:this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory)
		// 对Helper进行初始化,找advisor最终事委托给他了的
		// BeanFactoryAdvisorRetrievalHelperAdapter继承自BeanFactoryAdvisorRetrievalHelper,为私有内部类,主要重写了isEligibleBean()方法,调用.this.isEligibleAdvisorBean(beanName)方法
		initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
	}

	// 这是复写父类的方法,也是实现代理方式。找到作用在这个Bean里面的切点方法
	// 当然 最终最终事委托给BeanFactoryAdvisorRetrievalHelper去做的
	@Override
	@Nullable
	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		
		// findEligibleAdvisors:显然这个是具体的实现方法了。
		// eligible:合格的  合适的
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
	
	// 找出合适的Advisor们~~~  主要分了下面几步
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		
		// 首先找出所有的候选的Advisors,(根据名字判断)实现见下面~~~~
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 对上面找到的候选的Advisors们,进行过滤操作~~~  看看Advisor能否被用在Bean上(根据Advisor的PointCut判断)
		// 主要依赖于AopUtils.findAdvisorsThatCanApply()方法  在工具类讲解中有详细分析的
		// 逻辑简单概述为:看目标类是不是符合代理对象的条件,如果符合就把Advisor加到集合中,最后返回集合
		// 简单的说:它就是会根据ClassFilter和MethodMatcher等等各种匹配。(但凡只有有一个方法被匹配上了,就会给他创建代理类了)
		// 方法用的ReflectionUtils.getAllDeclaredMethods,**因此哪怕是私有方法,匹配上都会给创建的代理对象,这点务必要特别特别的注意**
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		
		//提供一个钩子。子类可以复写此方法  然后对eligibleAdvisors进行处理(增加/删除/修改等等)
		// AspectJAwareAdvisorAutoProxyCreator提供了实现
		extendAdvisors(eligibleAdvisors);
		
		// 如果最终还有,那就排序吧 
		if (!eligibleAdvisors.isEmpty()) {
			// 默认排序方式:AnnotationAwareOrderComparator.sort()排序  这个排序和Order接口有关~~~
			// 但是子类:AspectJAwareAdvisorAutoProxyCreator有复写此排序方法,需要特别注意~~~
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}


	// 找到候选的Advisor们~~~~   抽象类自己的实现,是直接把这件事委托给了advisorRetrievalHelper
	// 关于它的具体逻辑  后文问详细分析  毕竟属于核心逻辑
	// AnnotationAwareAspectJAutoProxyCreator对它有复写
	protected List<Advisor> findCandidateAdvisors() {
		Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}

	// 判断给定的BeanName这个Bean,是否是合格的(BeanFactoryAdvisorRetrievalHelper里会用到这个属性)
	// 其中:DefaultAdvisorAutoProxyCreator和InfrastructureAdvisorAutoProxyCreator有复写
	protected boolean isEligibleAdvisorBean(String beanName) {
		return true;
	}

	// 此处复写了父类的方法,返回true了,表示
	@Override
	protected boolean advisorsPreFiltered() {
		return true;
	}
}

我们发现这个抽象类主要是提供getAdvicesAndAdvisorsForBean()这个方法的获取模版(虽然它没有提供抽象方法给子类去实现,但子类复写了protected方法,改变了一些默认行为。但是各个实现类都各有不同,现在我们看看实现:)

从简单到复杂,从不用到常用,现在分析分析这些实现类:

DefaultAdvisorAutoProxyCreator

打个比方:它就是BeanNameAutoProxyCreator的加强版。如果说BeanNameAutoProxyCreator就是步枪需要自己装配,DefaultAdvisorAutoProxyCreator就是自动步枪了,Spring可以完成自动匹配的工作了

一般,我们只需要这样配置即可

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        return new DefaultAdvisorAutoProxyCreator();
    }

	// 还需要对应的Advisor(可以有多个~~)  从而给能够匹配上的创建代理对象了
    @Bean
    public NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor() {
        NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor = new NameMatchMethodPointcutAdvisor();
        
        //拦截到了HelloService#hello()方法,因此会给他创建代理对象
        nameMatchMethodPointcutAdvisor.addMethodName("*hello");
        
        // 请注意:此处虽然HelloController有个方法名叫helloGet,但是不会创建代理得。因为这在根容器里,这种情况不作用与子容器的Bean的
        nameMatchMethodPointcutAdvisor.addMethodName("helloGet"); 
        nameMatchMethodPointcutAdvisor.setAdvice(new MyMethodInteceptor());
        return nameMatchMethodPointcutAdvisor;
    }

这样它就会自动的去把Advisor匹配上的Bean进行代理掉。(不像BeanNameAutoProxyCreator还得手动指定BeanName,以及拦截器们)

一般都需要自己像容器注入自己的Advisor,比如NameMatchMethodPointcutAdvisor,否则它也不知道去代理谁嘛。只有被对应的Advisor匹配上的才会生成代理对象

它的源码很简单:它也是只复写了一个方法

	// Consider {@code Advisor} beans with the specified prefix as eligible, if activated.
	// 用到了前缀之类的。主要是考虑可以通过前缀匹配某一类Bean,而其他的Advisor我就不匹配了
	// 前缀的作用:进行分离匹配(而不是拿所有的Advisor~~)
	@Override
	protected boolean isEligibleAdvisorBean(String beanName) {
		if (!isUsePrefix()) {
			return true;
		}
		String prefix = getAdvisorBeanNamePrefix();
		return (prefix != null && beanName.startsWith(prefix));
	}
InfrastructureAdvisorAutoProxyCreator

Infrastructure:基础设施、基建

听这名字就知道,这是Spring给自己内部使用的一个自动代理创建器。这个类在@EnableTransactionManagement事务相关里会再次提到(它的AutoProxyRegistrar就是向容器注册了它),其实它的作用非常简单:主要是读取Advisor类,并对符合的bean进行二次代理

public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
	...
	// 没有其余多余代码 就这一个
	// bean工厂含有这个Bean,且这个Bean的Role是BeanDefinition.ROLE_INFRASTRUCTURE 系统内部用的  才返回true
	@Override
	protected boolean isEligibleAdvisorBean(String beanName) {
		return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
				this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
	}
}

接下来两个实现就和AspectJ相关了~~~相对来说比较难啃一点

AspectJAwareAdvisorAutoProxyCreator

顾名思义,该类主要来处理AspectJ切面的。这也是当下最流行,也是功能最为强大的一种方式吧~~~

它对父类,做了如下几点扩展:

// @since 2.0
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {

	// 默认的排序器,它就不是根据Order来了,而是根据@Afeter @Before类似的标注来排序
	private static final Comparator<Advisor> DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();

	// 核心逻辑:它重写了排序
	// 这个排序和`org.aspectj.util`提供的PartialOrder和PartialComparable有关 具体不详叙了
	// 这块排序算法还是比较复杂的,控制着最终的执行顺序~
	protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
		...
	}

	// 这个就是对已有的Advisor做了一个扩展:
	// AspectJProxyUtils这个工具类只有这一个方法  (其实每次addAspect()的时候,都会调用此方法)
	// Capable:能干的  有才华的
	// 它的作用:(若存在AspectJ的Advice),就会在advisors的第一个位置加入`ExposeInvocationInterceptor.ADVISOR`这个advisor
	@Override
	protected void extendAdvisors(List<Advisor> candidateAdvisors) {
		AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
	}

	
	// 这个相当于:
	@Override
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		
		// 这个相当于AspectJPointcutAdvisor的子类不要拦截、AspectJ切面自己自己的所有方法不要去拦截。。。
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
				return true;
			}
		}
		// 父类返回的false
		return super.shouldSkip(beanClass, beanName);
	}
	...
}

ExposeInvocationInterceptor 的作用是用于暴露 MethodInvocation 对象到 ThreadLocal 中,其名字也体现出了这一点。如果其他地方需要当前的 MethodInvocation 对象,直接通过调用静态方法 ExposeInvocationInterceptor.currentInvocation 方法取出。那哪些地方会用到呢???? AspectJExpressionPointcut#matches就有用到~~

AnnotationAwareAspectJAutoProxyCreator

首先AnnotationAwareAspectJAutoProxyCreator它是AspectJAwareAdvisorAutoProxyCreator的子类。

然后从名字中可议看出,它和注解有关。因此其实我们的**@EnableAspectJAutoProxy**它导入的就是这个**自动代理创建器**去帮我们创建和AspectJ相关的代理对象的。这也是我们当下使用最为广泛的方式~

// @since 2.0
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

	@Nullable
	private List<Pattern> includePatterns;
	//唯一实现类:ReflectiveAspectJAdvisorFactory
	// 作用:基于@Aspect时,创建Spring AOP的Advice
	// 里面会对标注这些注解Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class的方法进行排序
	// 然后把他们都变成Advisor( getAdvisors()方法 )
	@Nullable
	private AspectJAdvisorFactory aspectJAdvisorFactory;
	//该工具类用来从bean容器,也就是BeanFactory中获取所有使用了@AspectJ注解的bean
	//就是这个方法:aspectJAdvisorsBuilder.buildAspectJAdvisors()
	@Nullable
	private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;


	// 很显然,它还支持我们自定义一个正则的模版
	// isEligibleAspectBean()该方法使用此模版,从而决定使用哪些Advisor
	public void setIncludePatterns(List<String> patterns) {
		this.includePatterns = new ArrayList<>(patterns.size());
		for (String patternText : patterns) {
			this.includePatterns.add(Pattern.compile(patternText));
		}
	}
	
	// 可以自己实现一个AspectJAdvisorFactory  否则用默认的ReflectiveAspectJAdvisorFactory
	public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) {
		Assert.notNull(aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
	}

	// 此处一定要记得调用:super.initBeanFactory(beanFactory);
	@Override
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.initBeanFactory(beanFactory);
		if (this.aspectJAdvisorFactory == null) {
			this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
		}
		this.aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
	}


	// 拿到所有的候选的advisor们。请注意:这里没有先调用了父类的super.findCandidateAdvisors()  去容器里找出来一些
	// 然后,然后自己又通过aspectJAdvisorsBuilder.buildAspectJAdvisors()  解析@Aspect的方法得到一些Advisor
	@Override
	protected List<Advisor> findCandidateAdvisors() {
		List<Advisor> advisors = super.findCandidateAdvisors();
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}
	
	// 加了中类型   如果该Bean自己本身就是一个@Aspect, 那也认为是基础主键,不要切了
	@Override
	protected boolean isInfrastructureClass(Class<?> beanClass) {
		return (super.isInfrastructureClass(beanClass) ||
				(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
	}

	// 拿传入的正则模版进行匹配(没传就返回true,所有的Advisor都会生效)
	protected boolean isEligibleAspectBean(String beanName) {
		if (this.includePatterns == null) {
			return true;
		}
		else {
			for (Pattern pattern : this.includePatterns) {
				if (pattern.matcher(beanName).matches()) {
					return true;
				}
			}
			return false;
		}
	}
	...
}

AspectJAwareAdvisorAutoProxyCreator它用于xml配置版的AspectJ切面自动代理创建(<aop:config/>) AnnotationAwareAspectJAutoProxyCreator用于基于注解的自动代理创建(<aop:aspectj-autoproxy/> 或 @EnableAspectJAutoProxy)

BeanFactoryAdvisorRetrievalHelper:从Bean工厂检索出Advisor们

这个类很重要,是真正去容器中找出所有的Advisor的类

// @since 2.0.2
public class BeanFactoryAdvisorRetrievalHelper {

	private final ConfigurableListableBeanFactory beanFactory;
	// 本地会做一个简单的字段缓存
	@Nullable
	private String[] cachedAdvisorBeanNames;
	...
	
	// 这里显然就是核心方法了
	public List<Advisor> findAdvisorBeans() {
		String[] advisorNames = null;
		
		synchronized (this) {
			advisorNames = this.cachedAdvisorBeanNames;
			if (advisorNames == null) {
				// 这里不会实例化FactoryBeans
				// 我们需要保留所有常规bean未初始化以允许自动代理创建者应用于它们
				// 注意此处:连祖先容器里面的Bean都会拿出来  (这个方法平时我们也可以使用)
				advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Advisor.class, true, false);
				this.cachedAdvisorBeanNames = advisorNames;
			}
		}
		
		// 如果容器里面没有任何的advisor 那就拉倒吧
		if (advisorNames.length == 0) {
			return new LinkedList<>();
		}

		List<Advisor> advisors = new LinkedList<>();
		for (String name : advisorNames) {
			
			// isEligibleBean:表示这个bean是否是合格的,默认是true
			// 但上面书说了InfrastructureAdvisorAutoProxyCreator和DefaultAdvisorAutoProxyCreator都做了对应的复写
			if (isEligibleBean(name)) {
				// 如果当前Bean正在创建中  那好  就啥也不做吧
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipping currently created advisor '" + name + "'");
					}
				}
				// 否则就把这个Advisor加入到List里面,是个合法的
				else {
					try {
						advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
					catch (BeanCreationException ex) {
						... 
						continue;
					}
				}
			}
		}
		return advisors;
	}
	
	protected boolean isEligibleBean(String beanName) {
		return true;
	}

}



综上,整个Spring AOP中的自动代理创建器就全部介绍完了,相信收货不小吧~~~

不同的实现类都有自己不同的使用场景。但是在注解驱动大行其道的今天,显然AnnotationAwareAspectJAutoProxyCreator这个自动代理创建器是最流行、也是功能最强大、也是最实用的,所以是我们最应该掌握的~~~

总结

总的来说:Spring的知识是个体系,很多都是环环相扣的。学知识和建楼一样,需要从根基开始,否则永远只能是半桶水,容易洒出来

最后,只给使用的时候两个不成熟的小建议吧:

  1. SpringAOP应尽量避免自己创建AutoProxyCreator
  2. 避免使用低级别的AOP API

比如如下情况(我们自己注册一个创建器):

<bean class="org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator">  
    <property name="proxyTargetClass" value="true"/>  
</bean>  
<tx:annotation-driven transaction-manager="transactionManager"/>   

最终我却发现走的依旧是JDK动态代理,不是CGLIB。但是如果我这样:

<aop:aspectj-autoproxy proxy-target-class="true"/>  
<tx:annotation-driven transaction-manager="transactionManager"/>  

就一切正常,走的CGLIB了。至于什么原因,一语道不明,建议还是多看我博文掌握来龙去脉吧(哈哈~~~),读者可以自己思考咯~

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年04月16日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Spring中自动创建代理器(分类)
  • AbstractAutoProxyCreator
  • BeanNameAutoProxyCreator
  • AbstractAdvisorAutoProxyCreator 这是另一类自动代理方式
    • DefaultAdvisorAutoProxyCreator
      • InfrastructureAdvisorAutoProxyCreator
        • AspectJAwareAdvisorAutoProxyCreator
          • AnnotationAwareAspectJAutoProxyCreator
            • BeanFactoryAdvisorRetrievalHelper:从Bean工厂检索出Advisor们
              • 总结
                相关产品与服务
                容器服务
                腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档