注意: 先明白beanPostProcessor的作用,才能够明白aop的加载时机
在bean实例化完成之前和完成之后分别会自动BeanPostProcessor接口的postProcessBeforeInitialization和postProcessAfterInitialization方法。
advisorCreator,继承 spring ioc的扩展接口 beanPostProcessor,主要用来扫描获取 advisor。
beanPostProcessor作用: Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。
我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。
advisor:顾问的意思,封装了spring aop中的切点和通知。 就是我们常用的@Aspect 注解标记得类
advice:通知,也就是aop中增强的方法。
AbstractAutoProxyCreator:Spring 为Spring AOP 模块暴露的可扩展抽象类,也是 AOP 中最核心的抽象类。Nepxion Matrix 框架便是基于此类对AOP进行扩展和增强。
BeanNameAutoProxyCreator:根据指定名称创建代理对象(阿里大名鼎鼎的连接池框架druid也基于此类做了扩展)。通过设置 advisor,可以对指定的 beanName 进行代理。支持模糊匹配。
AbstractAdvisorAutoProxyCreator:功能比较强大,默认扫描所有Advisor的实现类。相对于根据Bean名称匹配,该类更加灵活。动态的匹配每一个类,判断是否可以被代理,并寻找合适的增强类,以及生成代理类。
DefaultAdvisorAutoProxyCreator:AbstractAdvisorAutoProxyCreator的默认实现类。可以单独使用,在框架中使用AOP,尽量不要手动创建此对象。
AspectJAwareAdvisorAutoProxyCreator:Aspectj的实现方式,也是Spring Aop中最常用的实现方式,如果用注解方式,则用其子类AnnotationAwareAspectJAutoProxyCreator。
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 findEligibleAdvisors(Class> beanClass, String beanName) {
//找到Spring中Advisor的实现类(findCandidateAdvisors)
//将所有拥有@Aspect注解的类转换为advisors(aspectJAdvisorsBuilder.buildAspectJAdvisors)
List candidateAdvisors = findCandidateAdvisors();
/* findAdvisorsThatCanApply
找到当前对象适合的所有Advisor。整个过程比较简单:
遍历所有的advisor。
查看当前advisor的pointCut是否适用于当前对象,如果是,进入候选队列,否则跳过。*/
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//添加一个默认的advisor,执行时用到。
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
findCandidateAdvisors:
protected List findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List 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 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 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 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 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使用配置:
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">
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的扩展接口中来创建代理类。