参考文章【小家Spring】Spring AOP的核心类:AbstractAdvisorAutoProxy自动代理创建器深度剖析(AnnotationAwareAspectJAutoProxyCreator)
SpringAOP面向切面编程应用结合实例,介绍了Spring AOP的过程以及对源码进行了逐步分析~
但是这中间当时事忽略了整个Spring AOP最为核心的一个类:自动代理创建器。
本文将主要以AnnotationAwareAspectJAutoProxyCreator
为引线,好好聊聊自动代理创建器是做什么的,具体做了什么,以及Spring为我们提供的其它几个Creator:DefaultAdvisorAutoProxyCreator
,InfrastructureAdvisorAutoProxyCreator
和AspectJAwareAdvisorAutoProxyCreator
,有何区别和对应的实用场景
可以看出来,所有的创建器都是AbstractAutoProxyCreator
该抽象类的子类~
当系统比较复杂,或者中需要进行aop进行织入的bean较多时,简单采用ProxyFacotryBean无疑会增加很多工作量(因为每个Bean都得手动写一个)。另外由于要从ProxyFactoryBean获得代理对象,也会使应用和Spring之间的耦合度增加,并且很多时候可维护性不强(我个人认为耦合这个不是最主要的原因,毕竟现在Spring已成为实际上的规范了)。
譬如,我们需要给bean名字满足“*service”的bean每个方法增加事务功能,如果采用ProxyFacotryBean必须为每个以service结尾的bean增加一个配置(工作量巨大),若需要修改,这个后果是灾难性的。
在内部,Spring使用BeanPostProcessor让自动生成代理。基于BeanPostProcessor的自动代理创建器的实现类,将根据一些规则在容器实例化Bean时为匹配的Bean生成代理实例。代理创建器可以分为三类:
1、BeanNameAutoProxyCreator
:基于Bean配置名规则的自动代理生成器:允许为一组特定配置名的Bean自动创建代理实例的代理创建器
2、DefaultAdvisorAutoProxyCreator
:基于Advisor匹配机制的自动代理创建器它会对容器中的所有Advisor进行扫描,自动将这些切面应用到匹配的Bean中
3、AbstractAdvisorAutoProxyCreator
:基于Bean中AspectJ注解的自动代理生成器:为包含AspectJ注解的切入的Bean自动创建代理实例
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
配置类上标注@EnableAspectJAutoProxy,会往容器注入类AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
//往容器中注入AnnotationAwareAspectJAutoProxyCreator的tBeanDefinition
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
// 若为true,表示强制指定了要使用CGLIB,那就强制告知到时候使用CGLIB的动态代理方式
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 告知,强制暴露Bean的代理对象到AopContext
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
AbstractAutoProxyCreator是对自动代理创建器的一个抽象实现。最重要的是,它实现了SmartInstantiationAwareBeanPostProcessor接口,因此会介入到Spring IoC容器Bean实例化的过程,因此由此为入口进行展开~
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);
...
// 这个很重要,在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;
}
// 这三个方法,没做什么动作~~
@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());
}
}
AbstractAutoProxyCreator的创建步骤就是上面源码分析的,它就相当于一个代理创建的模版,规定了一些步骤。获取Advisor的getAdvicesAndAdvisorsForBean由各子类自己去实现~~~
接下来主要是根据对方法getAdvicesAndAdvisorsForBean()的实现不一样,策略也就有两种了。它有两个直接实现:BeanNameAutoProxyCreator和AbstractAdvisorAutoProxyCreator。
顾名思义,它和Advisor无关,只和BeanName有关(只有名字匹配上了,都会给创建一个代理类)
所以我认为它是个半自动的,哪些需要创建代理,还需要我们自己指定(虽然支持*通配符)
public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
@Nullable
private List<String> beanNames;
//设置应该用代理自动包装的bean的名称
public void setBeanNames(String... beanNames) {
Assert.notEmpty(beanNames, "'beanNames' must not be empty");
this.beanNames = new ArrayList<>(beanNames.length);
for (String mappedName : beanNames) {
this.beanNames.add(StringUtils.trimWhitespace(mappedName));
}
}
// 这里面注意一点:BeanNameAutoProxyCreator的此方法并没有去寻找Advisor,所以需要拦截的话
// 只能依靠:setInterceptorNames()来指定拦截器。它是根据名字去Bean容器里取的
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
if (this.beanNames != null) {
for (String mappedName : this.beanNames) {
if (FactoryBean.class.isAssignableFrom(beanClass)) {
if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
continue;
}
mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
if (isMatch(beanName, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
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;
}
//simpleMatch并不是完整的正则。但是支持*这种通配符,其余的不支持哦
protected boolean isMatch(String beanName, String mappedName) {
return PatternMatchUtils.simpleMatch(mappedName, beanName);
}
}
案例
@Component
public class HelloService {
public void hello() {
System.out.println("调用hello方法...");
}
}
@Component
public class MyAspect implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("before");
}
}
@ComponentScan(value = {"aop"})
@Configuration
//@EnableAspectJAutoProxy
public class RootConfig {
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
// 给所有以serviceImpl结尾的类创建代理对象(支持正则) 备注:aliases也是被支持的
// 注意此处若只写`*Service` 是匹配不上helloServiceImpl
beanNameAutoProxyCreator.setBeanNames("helloService");
// 备注:它要想使用拦截,只能通过setInterceptorNames,从容器内拿Advice的实现类(自己书写)
beanNameAutoProxyCreator.setInterceptorNames("myAspect");
return beanNameAutoProxyCreator;
}
}
public class App {
public static void main( String[] args ) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(RootConfig.class);
((HelloService)annotationConfigApplicationContext.getBean("helloService")).hello();
}
}
程序输出:
before
调用hello方法...
备注:此时我们采用了BeanNameAutoProxyCreator,自然就不用再@EnableAspectJAutoProxy,自然@Aspect切面也就不生效了。 当然,也可以开启的,这样他俩就联合生效了(但不太建议去这么使用)
另外,如果你想用自己注册的@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环境下不好控制~)
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方法,改变了一些默认行为。但是各个实现类都各有不同,现在我们看看实现:)
从简单到复杂,从不用到常用,现在分析分析这些实现类:
个比方:它就是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匹配上的才会生成代理对象
它的源码很简单:它也是只复写了一个方法
public class DefaultAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator implements BeanNameAware {
// 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));
}
}
顾名思义,该类主要来处理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它是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的知识是个体系,很多都是环环相扣的。学知识和建楼一样,需要从根基开始,否则永远只能是半桶水,容易洒出来
最后,只给使用的时候两个不成熟的小建议吧:
SpringAOP应尽量避免自己创建AutoProxyCreator
避免使用低级别的AOP API