目录
二、findAdvisorsThatCanApply从所有切面中获取可用的切面
1)、父类中 findAdvisorsThatCanApply
4-1、 getAdvisorMethods(aspectClass)
4-2-2、InstantiationModelAwarePointcutAdvisorImpl
4-3、DeclareParentsAdvisor(引介增强)
我们现在基本都会使用@Aspect方式进行Aop,为了理解方便比如当前注解类如下,类上注解为@Aspect,方法上注解为:
@Pointcut("")、@Around("timeConsumeAspect()")、@After("timeConsumeAspect()") ,如下:
@Aspect
@Slf4j
public class TimeConsumeAction {
/**
* 只切面 TimeConsume 注解标注的方法
*/
@Pointcut("@annotation(com.kevin.tool.timeconsume.TimeConsume)")
private void timeConsumeAspect() {
}
/**
* Aop环绕
* @param pjp 切入点信息
* @return 代理对象
* @throws Throwable 执行异常
*/
@Around("timeConsumeAspect()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
return pjp.proceed();
}
/**
* Aop后置方法
* @param pjp 切入点信息
* @throws Throwable
*/
@After("timeConsumeAspect()")
public void after(JoinPoint pjp) {
}
private TimeConsume getTimeConsume(JoinPoint pjp) {
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method method = methodSignature.getMethod();
return method.getAnnotation(TimeConsume.class);
}
}
比如添加切面的目标类如下:
@Service
public class UserService {
@Autowired
private UserDao userDao;
@TimeConsume(taskName = "UserService.getInit")
@Async("createOrder")
public Integer getInit() throws InterruptedException {
Thread.sleep(3000);
userDao.getInit();
return 2;
}
@TimeConsume(taskName = "UserService.getInr", print = true)
@Async("createOrder")
public Integer getInr(int i) throws InterruptedException {
Thread.sleep(2000);
return userDao.getInr(i);
}
}
获取切面:getAdvicesAndAdvisorsForBean方法,如下:
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
继续findEligibleAdvisors方法:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
一、findAdvisorBeans获取所有可用的切面
// 从Bean工厂中获取所有Advisor(切面)的子类
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// 根据名称从BeanFactory中获取切面的Bean实例
List<Advisor> advisors = new ArrayList<>();
advisors.add(this.beanFactory.getBean(name, Advisor.class));
二、findAdvisorsThatCanApply从所有切面中获取可用的切面
AnnotationAwareAspectJAutoProxyCreator中实现了该方法:
@Override
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.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
1)、父类中 findAdvisorsThatCanApply
执行相当于加了一个线程锁,在判断,主要方法是在AopUtils中完成的:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
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;
}
先判断是否是引介切面,后在判断put切面,但是最终都会进入canApply方法:
public static boolean canApply(Advisor advisor, Class<?> targetClass,
boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
引介切面则获取内部的ClassFilter的matches方法进行判断,普通切面在调用canApply方法,方法内容太多就不进行分析了,主要是调用match方法进行判断。
2)、本类中 buildAspectJAdvisors
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
之前看过,初始化的aspectJAdvisorsBuilder 为 BeanFactoryAspectJAdvisorsBuilderAdapter类型,其内部属性AspectJAdvisorFactory为 ReflectiveAspectJAdvisorFactory类型。
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// 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);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
1、BeanFactory中获取Object的子类
第一次进来都是空的(我debug好几千个beanNames)
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
2、遍历,根据名称获取Class<?>
Class<?> beanType = this.beanFactory.getType(beanName);
3、判断是否是AspectJ注解
if (this.advisorFactory.isAspect(beanType)) 当前的advisorFactory为:ReflectiveAspectJAdvisorFactory,compiledByAjc判断所有的字段是否有以 "ajc$" 开头的。就会拿到我们上面标有@Aspect的类。
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
4、根据Bean名称获取AspectJ增强
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
@Override
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<>();
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.
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
4-1、 getAdvisorMethods(aspectClass)
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
methods.sort(METHOD_COMPARATOR);
return methods;
}
判断我们自己标记的@Aspect的类的所以方法,只有不含有@Pointcut的方法才会添加到List中,那么上面的方法带有@Pointcut的方法就没有被添加进去,但是我们的private方法getTimeConsume却被添加进去了。
顺序依次为:after、getTimeConsume、around
再执行排序:methods.sort(METHOD_COMPARATOR);
排序后的顺序为:around、after、getTimeConsume
排序的比较器在static静态代码块中定义,根据方法名称按照定义的顺序进行排序:
4-2、getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod,
MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod,
aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut,
candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
4-2-1、getPointcut
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
根据方法信息,调用findAspectJAnnotationOnMethod方法进行判断,就是循环遍历是否为下面的类型,排除掉getTimeConsume方法:
再去new 一个AspectJExpressionPointcut类型返回
4-2-2、InstantiationModelAwarePointcutAdvisorImpl
根据AspectJExpressionPointcut的切点,new一个InstantiationModelAwarePointcutAdvisorImpl类型的切面,进行返回。
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
构造函数内部看似复杂,其实最主要的是初始化instantiatedAdvice = instantiateAdvice(this.declaredPointcut),即对当前切面内的增强的处理。之前获取到了增强信息,和增强上的Spring Expression字符串,但是还没有进行解析。
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);
}
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
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);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
比较清楚了,根据不同的注解类型,初始化AspectJ类型的增强(Advice)。这样,增强初始化完成,切入点确认,切面也初始化完成。
4-3、DeclareParentsAdvisor(引介增强)
判断所有字段(包括私有)是否有添加@DeclareParents注解,则返回DeclareParentsAdvisor类型的增强。
aspectClass.getDeclaredFields()
private Advisor getDeclareParentsAdvisor(Field introductionField) {
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
if (declareParents == null) {
// Not an introduction field
return null;
}
if (DeclareParents.class == declareParents.defaultImpl()) {
throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
}
return new DeclareParentsAdvisor(
introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
}
四、获取继承关系的增强
在父类AspectJAwareAdvisorAutoProxyCreator中进行了重写,就是判断是否需要添加默认的拦截器。
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
// Be careful not to get the Advice without a guard, as this might eagerly
// instantiate a non-singleton AspectJ aspect...
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
当前Advisor中包含了AspectJ的拦截器,并且没有DefaultPointcutAdvisor(默认拦截器,并且Advice为ExposeInvocationInterceptor类型)则把默认拦截器加在第一位。当前目标类UserService则已经获取到了三个增强,并且顺序为:
org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR
InstantiationModelAwarePointcutAdvisorImpl类型的around增强(我们自己添加@Around的方法封装)
InstantiationModelAwarePointcutAdvisorImpl类型的after增强(我们自己添加@After的方法封装)
五、对增强进行排序
AnnotationAwareOrderComparator.sort(advisors);
总结:
先回顾一下大前提,每个Bean的实例化 BeanFactory.getBean(。。。),都会调用该方法:
1、获取所有BeanFactory中Advisor的子类,进行缓存
2、从所有的前面中遍历匹配当前Class的增强,分为两部分
1)、父类AbstractAdvisorAutoProxyCreator中,根据Class调用canApply进行判断,最后返回Advisor子类Bean
2)、AnnotationAwareAspectJAutoProxyCreator自己中,是处理@Aspect的类。分为两部分,方法(普通增强)、字段(引介增强)
处理普通切面:比较暴力,在BeanFactory中获取所有Object子类的Bean进行遍历,判断是否在类上添加@Aspect注解。有的话获取所有不包含@Pointcut的方法。在根据方法名称按照(Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class)匹配和排序。就拿到了切点方法,new AspectJExpressionPointcut类型的切点,再new InstantiationModelAwarePointcutAdvisorImpl类型切面进行返回。
进阶切面:获取方法的所有字段,判断是否有添加@DeclareParents注解,则new DeclareParentsAdvisor切面进行返回。
3、获取继承的增强
4、对增强进行排序
这样就完成了根据Bean名称和类获取排序好的增强就完成了,等到AbstractApplicationContext的refresh的最后,加载单利非懒加载的Bean调用完。所有该处理的Aop类都处理完了。但是这只是获取到了增强,还应该根据当前的切面(this)去创建切面,获取代理等待被调用。