注意: 先明白beanPostProcessor的做用,才可以明白aop的加载时机html
在bean实例化完成以前和完成以后分别会自动BeanPostProcessor接口的postProcessBeforeInitialization和postProcessAfterInitialization方法。spring
advisorCreator,继承 spring ioc的扩展接口 beanPostProcessor,主要用来扫描获取 advisor。express
beanPostProcessor做用: Spring容器中完成bean实例化、配置以及其余初始化方法先后要添加一些本身逻辑处理。缓存
咱们须要定义一个或多个BeanPostProcessor接口实现类,而后注册到Spring IoC容器中。
advisor:顾问的意思,封装了spring aop中的切点和通知。 就是咱们经常使用的@Aspect 注解标记得类
advice:通知,也就是aop中加强的方法。springboot
AbstractAutoProxyCreator:Spring 为Spring AOP 模块暴露的可扩展抽象类,也是 AOP 中最核心的抽象类。Nepxion Matrix 框架即是基于此类对AOP进行扩展和加强。框架
BeanNameAutoProxyCreator:根据指定名称建立代理对象(阿里大名鼎鼎的链接池框架druid也基于此类作了扩展)。经过设置 advisor,能够对指定的 beanName 进行代理。支持模糊匹配。ide
AbstractAdvisorAutoProxyCreator:功能比较强大,默认扫描全部Advisor的实现类。相对于根据Bean名称匹配,该类更加灵活。动态的匹配每个类,判断是否能够被代理,并寻找合适的加强类,以及生成代理类。函数
DefaultAdvisorAutoProxyCreator:AbstractAdvisorAutoProxyCreator的默认实现类。能够单独使用,在框架中使用AOP,尽可能不要手动建立此对象。post
AspectJAwareAdvisorAutoProxyCreator:Aspectj的实现方式,也是Spring Aop中最经常使用的实现方式,若是用注解方式,则用其子类AnnotationAwareAspectJAutoProxyCreator。ui
AnnotationAwareAspectJAutoProxyCreator:目前最经常使用的AOP使用方式。spring aop 开启注解方式以后,该类会扫描全部@Aspect()注释的类,生成对应的advisor。目前SpringBoot框架中默认支持的方式,自动配置。
图片来自于: https://www.cnblogs.com/yuxiang1/archive/2018/06/19/9199730.html
1: 建立AnnotationAwareAspectJAutoProxyCreator
对象
2: 扫描容器中的切面,建立PointcutAdvisor
对象
3: 生成代理类
PointcutAdvisor
对象的过程:能够看到在AbstractAutoProxyCreator类中的上层接口实现了BeanPostProcessor接口,
对于下面两个方法, 重写的第一个方法,其主要目的在于若是用户使用了自定义的TargetSource对象,则直接使用该对象生成目标对象,而不会使用Spring的默认逻辑生成目标对象,而且这里会判断各个切面逻辑是否能够应用到当前bean上,若是能够,则直接应用,也就是说TargetSource为使用者在Aop中提供了一个自定义生成目标bean逻辑的方式,而且会应用相应的切面逻辑。对于第二个方法,其主要做用在于Spring生成某个bean以后,将相关的切面逻辑应用到该bean上,
了解细致的TargetSource原理请参考:
https://blog.csdn.net/zxfryp909012366/article/details/82881659
1. 如下是bean实例化以后, 初始化以前操做postProcessBeforeInstantiation
在AbstractAutoProxyCreator类中实现BeanPostProcessor中的下面方法中:
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { //advisedBeans用于存储不可代理的bean,若是包含直接返回 if (this.advisedBeans.containsKey(cacheKey)) { return null; } //判断当前bean是否能够被代理,而后存入advisedBeans 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. //获取封装当前bean的TargetSource对象,若是不存在,则直接退出当前方法,不然从TargetSource // 中获取当前bean对象,而且判断是否须要将切面逻辑应用在当前bean上。 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } // 获取可以应用当前bean的切面逻辑 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); // 对生成的代理对象进行缓存 this.proxyTypes.put(cacheKey, proxy.getClass()); //若是最终能够得到代理类,则返回代理类,直接执行实例化后置通知方法 return proxy; } return null; }
================================================================================================
2. 如下是bean初始完成以后建立代理对象过程:postProcessAfterInitialization
在AbstractAutoProxyCreator类中实现BeanPostProcessor中的下面方法中:
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { //缓存键:1.beanName不为空的话,使用beanName(FactoryBean会在见面加上"&") //2.若是beanName为空,使用Class对象做为缓存的key Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { //若是条件符合,则为bean生成代理对象 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
wrapIfNecessary:
代码流程:
1. 若是已经处理过,且该bean没有被代理过,则直接返回该bean
2.若是该bean是内部基础设置类Class 或 配置了该bean不须要代理,则直接返回bean(返回前标记该bean已被处理过)
3.获取全部适合该bean的加强Advisor
若是加强不为null,则为该bean建立代理对象,并返回结果
标记该bean已经被处理过
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //若是已经处理过(targetSourcedBeans存放已经加强过的bean) if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } //advisedBeans的key为cacheKey,value为boolean类型,表示是否进行过代理 //已经处理过的bean,不须要再次进行处理,节省时间 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //是不是内部基础设置类Class || 配置了指定bean不须要代理,若是是的话,直接缓存。 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 获取当前对象全部适用的Advisor.加入当前对象是orderController,那么找到全部切点是他的对应的@Aspect注解的类 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); //若是获取的加强不为null,则为该bean建立代理(DO_NOT_PROXY=null) if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); //建立代理对象时候会用到是否进行JDK代理或者CGLIB代理 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } //标记该cacheKey已经被处理过 this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
AspectJAwareAdvisorAutoProxyCreator的实现wrapIfNecessary方法中判断是否为基础类的方法:
protected boolean isInfrastructureClass(Class<?> beanClass) { //若是bean继承自Advice、Pointcut、Advisor、AopInfrastructureBean boolean retVal = Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass); if (retVal && logger.isTraceEnabled()) { logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]"); } return retVal; }
从上面代码能够看出,继承自Advice、Pointcut、Advisor、AopInfrastructureBean没法被加强
AnnotationAwareAspectJAutoProxyCreator 继承了AspectJAwareAdvisorAutoProxyCreator 类 调用父类方法时候
在isInfrastructureClass时候,同时加了isAspect方法实现:
public boolean isAspect(Class<?> clazz) { //若是bean带有@Aspect注解,或被Ajc(AspectJ编译器)编译 return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz)); }
综上,若是一个bean继承自Advice、Pointcut、Advisor、AopInfrastructureBean 或者 带有@Aspect注解,或被Ajc(AspectJ编译器)编译都会被认定为内部基础设置类
在AnnotationUtils类中的findAnnotation方法中,判断这个bean上的注解类型是否是@Aspect
以上②逻辑原文: https://blog.csdn.net/finalcola/article/details/82108745
同时AspectJAwareAdvisorAutoProxyCreator的实现wrapIfNecessary方法中判断是否要进行代理的方法getAdvicesAndAdvisorsForBean同时会调用
findEligibleAdvisors处理两件事:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //找到Spring中Advisor的实现类(findCandidateAdvisors) //将全部拥有@Aspect注解的类转换为advisors(aspectJAdvisorsBuilder.buildAspectJAdvisors) List<Advisor> candidateAdvisors = findCandidateAdvisors(); /* findAdvisorsThatCanApply 找到当前对象适合的全部Advisor。整个过程比较简单: 遍历全部的advisor。 查看当前advisor的pointCut是否适用于当前对象,若是是,进入候选队列,不然跳过。*/ List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); //添加一个默认的advisor,执行时用到。 extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
findCandidateAdvisors:
protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
super.findCandidateAdvisors()
方法最终调用的是BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans()
方法,咱们首先看看该方法的实现:
public List<Advisor> findAdvisorBeans() { String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // 获取当前BeanFactory中全部实现了Advisor接口的bean的名称 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList<>(); } // 对获取到的实现Advisor接口的bean的名称进行遍历 List<Advisor> advisors = new LinkedList<>(); for (String name : advisorNames) { // isEligibleBean()是提供的一个hook方法,用于子类对Advisor进行过滤,这里默认返回值都是true if (isEligibleBean(name)) { // 若是当前bean还在建立过程当中,则略过,其建立完成以后会为其判断是否须要织入切面逻辑 if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { // 将当前bean添加到结果中 advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { // 对获取过程当中产生的异常进行封装 Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; String bceBeanName = bce.getBeanName(); if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) { if (logger.isDebugEnabled()) { logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } continue; } } throw ex; } } } } return advisors; }
而后其中的 buildAspectJAdvisors
方法,会触发ReflectiveAspectJAdvisorFactory
中的getAdvisors
方法:
@Override public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { //从 aspectMetadata 中获取 Aspect()标注的类 class对象 Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); //获取Aspect()标注的类名 String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass); // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator // so that it will only instantiate once. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new LinkedList<>(); //遍历该类全部方法,根据方法判断是否能获取到对应 pointCut,若是有,则生成 advisor 对象 for (Method method : getAdvisorMethods(aspectClass)) { //这里继续看下面的解析 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); if (advisor != null) { advisors.add(advisor); } } // If it's a per target aspect, emit the dummy instantiating aspect. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } // Find introduction fields. //获取 @DeclareParents 注解修饰的属性(并不经常使用) for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; }
继续来看getAdvisor
方法:
@Override @Nullable public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); //根据候选方法名,来获取对应的 pointCut AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } //若是能获取到 pointCut,则将切点表达式 expressionPointcut、当前 对象ReflectiveAspectJAdvisorFactory、 方法名等包装成 advisor 对象 return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); }
InstantiationModelAwarePointcutAdvisorImpl
的构造方法会触发构造通知对象:
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { //...... //根据注解类型,匹配对应的通知类型 switch (aspectJAnnotation.getAnnotationType()) { //前置通知 case AtBefore: springAdvice = new AspectJMethodBeforeAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; //最终通知 case AtAfter: springAdvice = new AspectJAfterAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; //后置通知 case AtAfterReturning: springAdvice = new AspectJAfterReturningAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; //异常通知 case AtAfterThrowing: springAdvice = new AspectJAfterThrowingAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; //环绕通知 case AtAround: springAdvice = new AspectJAroundAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; //切面 case AtPointcut: if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; default: throw new UnsupportedOperationException( "Unsupported advice type on method: " + candidateAdviceMethod); } //...... }
能够看到,根据@Aspect
类中方法的注解类型,生成对应的advice
,并经过通知的构造方法,将通知加强方法,切面表达式传入到通知当中。
到这里InstantiationModelAwarePointcutAdvisorImpl
对象构造完毕。
原文:https://blog.csdn.net/uftjtt/article/details/80076733
Spring XML关于ProxyFactoryBean使用配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 业务Bean -->
<bean name="conferenceService" class="com.lanhuigu.spring.ConferenceServiceImpl"></bean>
<!--配置Advice-->
<bean name="logAdvice" class="com.lanhuigu.spring.aop.LoggerAdvice"></bean>
<!--配置ProxyFactoryBean-->
<bean name="aopMethod" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 指定通知器 -->
<property name="interceptorNames">
<list>
<value>logAdvice</value>
</list>
</property>
<!-- 须要加强的类 -->
<property name="target" ref="conferenceService"/>
</bean>
</beans>
AopProxy代理对象的生成过程:
最后咱们回到最初的AbstractAutoProxyCreator中的createProxy方法中
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 = new ProxyFactory(); //获取当前类中的属性 proxyFactory.copyFrom(this); //检查proxyTargeClass设置以及preserveTargetClass属性 //决定对于给定的bean是否应该使用targetClass而不是他的接口代理 if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { //用来添加代理接口 evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); //加入加强器 proxyFactory.addAdvisors(advisors); //设置要代理的类 proxyFactory.setTargetSource(targetSource); //定制代理 customizeProxyFactory(proxyFactory); //用来控制代理工厂被设置后是否还容许修改通知,缺省值为false proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
从上面代码咱们看到对于代理类的建立及处理spring是委托给了ProxyFactory处理的,而在此函数中主要是对ProxyFactory的初始化操做,进而对建立代理作准备,这些初始化操做包括如下内容:
(1)获取当前类中的属性
(2)添加代理接口
下面是添加代理接口evaluateProxyInterfaces的函数:
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) { Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader()); boolean hasReasonableProxyInterface = false; for (Class<?> ifc : targetInterfaces) { if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) && ifc.getMethods().length > 0) { hasReasonableProxyInterface = true; break; } } if (hasReasonableProxyInterface) { // Must allow for introductions; can't just set interfaces to the target's interfaces only. for (Class<?> ifc : targetInterfaces) { proxyFactory.addInterface(ifc); } } else { proxyFactory.setProxyTargetClass(true); } }
(3)封装Advisor并加入到ProxyFactory中
(4)设置要代理的类
(5)在spring中还为子类提供了定制的函数customizeProxyFactory,子类能够在此函数中进行对ProxyFactory的进一步封装
(6)进行获取代理操做
在createProxy方法最后返回的getProxy方法中能够看到
public Object getProxy(@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
在上面的getProxy方法中createAopProxy方法,其实现是在DefaultAopProxyFactory中,咱们进入到方法内:
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
配置类AopAutoConfiguration:
1.5x版本:
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = false)
public static class CglibAutoProxyConfiguration {
}
2.x版本:
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
能够看到,在SpringBoot2.x中最主要的变化就是proxy-target-class默认为true,意味着类代理的时候所有走cglib代理方式,只有为接口代理时才走jdk代理(注意:这里为接口代理,不是指代理目标类是否实现了接口)。因此,在使用springboot2.x的版本中,除了代理目标类是接口外,其他的代理方式所有采用cglib类型。
总结
Springboot经过自动装配AopAutoConfiguration配置类,默认自动开启 AOP 功能。经过注册 AnnotationAwareAspectJAutoProxyCreator类,来扫描建立全部的Advisor,再经过 Advisor在 Spring IOC的扩展接口中来建立代理类。