在《Spring AOP源码分析(上)》介绍了在Spring AOP生成代理对象并作为Bean实例,以及@Before、@Around等注解的解析都是靠@EnableAspectJAutoProxy注解来完成的,这篇文章重点介绍该注解是如何实现上述功能的
一、注册AutoProxyCreator
@EnableAspectJAutoProxy注解如下,该注解通过@Import来加载AspectJAutoProxyRegistrar配置类,该配置类实现了ImportBeanDefinitionRegistrar接口,可以通过接口的registerBeanDefinitions()方法注册BeanDefinition
同时,@EnableAspectJAutoProxy提供了两个属性,proxyTargetClass()为true时会使用CGLIB进行动态代理,exposeProxy()为true时会把生成的代理对象添加到当前线程的ThreadLocal中
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
注册AnnotationAwareAspectJAutoProxyCreator,如果@EnableAspectJAutoProxy的属性为true,就把这两个属性值添加到AnnotationAwareAspectJAutoProxyCreator的BeanDefinition的propertyValues中
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 注册一个AnnotationAwareAspectJAutoProxyCreator类型的Bean,beanName为AUTO_PROXY_CREATOR_BEAN_NAME
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 修改AnnotationAwareAspectJAutoProxyCreator中对应的属性
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
添加proxyTargetClass属性值
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
二、生成代理对象
AnnotationAwareAspectJAutoProxyCreator继承自AbstractAutoProxyCreator,是一个BeanPostProcessor,在Bean实例创建过程的初始化后中,会调用postProcessAfterInitialization()方法判断是否需要进行AOP,如果需要AOP则创建一个代理对象返回
该方法在解决循环依赖的时候也有用到,如果当前Bean已经进行过AOP,则不会再次执行,否则将会调用wrapIfNecessary()方法来判断是否需要进行AOP以及生成AOP代理对象
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
2.1 判断是否需要进行AOP
如果缓存advisedBeans已经记录了当前beanName不需要进行AOP,就直接返回
isInfrastructureClass()判断当前Bean是否为Advice、Pointcut、Advisor或AopInfrastructureBean,这些接口的实现类不能进行AOP,并且缓存一下这些Bean不能进行AOP
通过getAdvicesAndAdvisorsForBean()查找相匹配的Advisor,如果存在相匹配的,则需要进行AOP
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 当前正在创建的Bean不用进行AOP,比如切面Bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
……
}
isInfrastructureClass()源码
protected boolean isInfrastructureClass(Class<?> beanClass) {
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;
}
2.2 查找Advisor
getAdvicesAndAdvisorsForBean()方法中调用findEligibleAdvisors()查找Advisor
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 寻找匹配的Advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
调用findCandidateAdvisors()方法找到所有Advisor,然后进行筛选,最近对这些Advisor按照order值进行排序
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到所有的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 进行筛选
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
// 对Advisor进行排序,按Ordered接口、@Order注解进行排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
在Spring AOP中,查找Advisor分为两类,一种是实现了Advisor接口,另一种是在切面类中通过@Before、@Around等注解定义的Advisor
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 先找到所有Advisor类型的Bean对象
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
// 再从所有切面中解析得到Advisor对象
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
2.2.1 查找实现Advisor接口的Advisor
通过beanNamesForTypeIncludingAncestors()获取所有实现了Advisor接口的BeanDefinition的beanName,然后通过getBean()方法创建Bean实例,然后添加到advisors中返回
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
for (String name : advisorNames) {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
return advisors;
}
2.2.2 查找切面类中的Advisor
把所有的beanName都拿出来,然后根据Bean类型依次判断是否有Aspect注解,如果有该注解,则调用getAdvisors()获取切面中的Advisor
public List<Advisor> buildAspectJAdvisors() {
// aspectBeanNames是用来缓存BeanFactory中所存在的切面beanName的,第一次为null,后面就不为null了,不为null表示之前就已经找到过BeanFactory中的切面了
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
// 把所有beanNames拿出来遍历,判断某个bean的类型是否是Aspect
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName, false);
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
// 如果@Aspect不是perthis、pertarget,那么一个切面只会生成一个对象(单例)
// 并且会将该切面中所对应的Advisor对象进行缓存
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 利用BeanFactoryAspectInstanceFactory来解析Aspect类
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 缓存切面所对应的所有Advisor对象
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
}
……
}
}
}
}
}
通过getAdvisorMethods获取切面类的方法,然后调用getAdvisor()生成Advisor对象
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
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 ArrayList<>();
// 获取切面类中没有加@Pointcut的方法,进行遍历生成Advisor
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
……
return advisors;
}
getAdvisorMethods()方法获取切面类中所有没有加@Pointcut注解的方法,然后对方法进行排序
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
List<Method> methods = new ArrayList<>();
// 拿到切面类中所有没有加@Pointcut的方法
ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
// 对方法进行排序,按注解和方法名字进行排序
if (methods.size() > 1) {
methods.sort(adviceMethodComparator);
}
return methods;
}
private static final MethodFilter adviceMethodFilter = ReflectionUtils.USER_DECLARED_METHODS
.and(method -> (AnnotationUtils.getAnnotation(method, Pointcut.class) == null));
排序规则如下:
按照Around、Before、After、AfterReturning、AfterThrowing注解优先级进行排序,具有相同注解的方法按照方法名进行排序
private static final Comparator<Method> adviceMethodComparator;
static {
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
new InstanceComparator<>(
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (ann != null ? ann.getAnnotation() : null);
});
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);
}
getAdvisor()方法中,首先获取Pointcut对象,然后实例InstantiationModelAwarePointcutAdvisorImpl,生成Advisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 拿到当前方法所对应的Pointcut对象,但是注意:如果当前方法上是这么写的@After("pointcut()"),那么此时得到的Pointcut并没有去解析pointcut()得到对应的表达式
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// expressionPointcut是pointcut
// candidateAdviceMethod承载了advice
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
在InstantiationModelAwarePointcutAdvisorImpl方法中,会通过instantiateAdvice()得到一个Advisor,
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
……
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 通过切点和方法信息得到一个Advice对象,提醒:当前是在Advisor内部了
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
instantiateAdvice()方法实现如下:
通过getAdvice()去生成一个Advisor
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
在ReflectiveAspectJAdvisorFactory的getAdvice()方法中,会去解析方法上的注解,然后根据注解类型,生成对应的Advisor
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
// 拿到当前candidateAdviceMethod方法上的注解信息
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
……
AbstractAspectJAdvice springAdvice;
// 按不同的注解类型得到不同的Advice
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
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;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
return springAdvice;
}
2.3 筛选Advisor
通过canApply()筛选Advisor,筛选逻辑同上一篇文章《Spring AOP源码分析(中)》
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
先判断类是否匹配,再判断类中的方法是否匹配
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// 判断targetClass是不是和当前Pointcut匹配
// 先判断类
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
……
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
// 在判断方法是否匹配
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
2.4 生成代理对象
如果找到匹配的Advisor,将当前Bean封装成SingletonTargetSource,调用createProxy生成代理对象并返回
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// advisedBeans记录了某个Bean已经进行过AOP了
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/153651.html