在分析流程之前,我们先简单的实现一下AOP。
@Component
@ComponentScan("com.jxau")
public class EnableComponentScan {
}
定义一个扫描包。然后创建一个类开启AOP的扫描注解
@Component
@EnableAspectJAutoProxy(exposeProxy = true)
public class EnableAop {
}
定义一个切面。
@Component
@Aspect
public class AspectJ {
//拦截service包下所有类
@Pointcut("execution(public * com.jxau.service.*.*(..))")
public void pointCut1(){
}
//拦截service包下的saveAccount方法
@Pointcut("execution(public * com.jxau.service.*.saveAccount*(..))")
public void pointCut2(){}
//使用pointCut2
@Before("pointCut2()")
public void beforeAdvice(){
System.out.println("before前置通知");
}
//使用pointCut1
@Around("pointCut1()")
public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable {
System.out.println("around的前置通知");
Object proceed = point.proceed();
System.out.println("around的后置通知");
return proceed;
}
@After("execution(public * com.jxau.service.*.*(..))")
public void afterMethod(){
System.out.println("afterMethod");
}
@AfterReturning("execution(public * com.jxau.service.*.*(..))")
public void returnMethod(){
System.out.println("returnMethod");
}
}
然后定义一个被切的类。
public interface AccountService {
public void saveAccount();
}
@Service
class AccountServiceImpl implements AccountService {
public void saveAccount() {
System.out.println("saceAccount");
}
}
其实这个时候,我们就可以启动了。
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(EnableComponentScan.class);
AccountService bean = applicationContext.getBean(AccountService.class);
bean.saveAccount();
运行结果。
这样,我们的一个简单的demo就搭建完成了。下面我们来分析一下他的执行流程。
@EnableAspectJAutoProxy
那其实呢,我们整个AOP,其实就是这个注解所开启的,那么这个注解到底做了什么。
其实,不管是@Service还是@Component都会被@ComponentScan注解扫描到,具体如何被扫描的,是从AnnotationConfigApplicationContext入口,在该方法中,会通过ComponentScan注解,然后像解析自定义标签一样,扫描basePackages下的带注解的类,封装为BeanDefinition,然后会遍历这些BeanDefinition,看看其类上有没有@Import、@Compontent等注解,如果有,会继续将涉及的类注册到IOC容器中,因此,我们这个注解之上的import注解就一定会被扫描到,而且会导入一个AspectJAutoProxyRegistrar的类,那看来这个类就是我们的重点了。
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//注册注解AOP入口类
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
这个类中除了构造,其实也就只有这么一个方法,而这个方法会被beanFactory注册beanDefinition的时候调用,核心在第一句代码,我们一步步进去之后,会看到这样的方法。
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
} else {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", -2147483648);
beanDefinition.setRole(2);
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}
那这个方法其实也比较简单了,就是注册一个BeanDefinition ,registry.registerBeanDefinition(“org.springframework.aop.config.internalAutoProxyCreator”, beanDefinition);也很明确的告诉我们,注册的这个BeanDefinition 就是AnnotationAwareAspectJAutoProxyCreator.class,他的key值是org.springframework.aop.config.internalAutoProxyCreator,这个BeanDefinition 有很重要的作用。
AOP入口
applyBeanPostProcessorsAfterInitialization
其实在bean实例化和依赖注入的时候,有个位置是AOP的入口,AOP想要用原类,那么一定在该类实例化和依赖注入完成后才可以用,因此AOP入口是在doCreateBean的populateBean方法(实例化后的依赖注入)后进行,即initializeBean方法,如下:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
.....
}
else {
//调用Aware方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//调用@PostConstruct,Aware等接口方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//调用InitializingBean接口的afterPropertiesSet方法和init-method
invokeInitMethods(beanName, wrappedBean, mbd);
}
.................
}
if (mbd == null || !mbd.isSynthetic()) {
//这里就是AOP的入口了
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
这里的意图也很明显,就是遍历所有的BeanPostProcessor接口,调用postProcessAfterInitialization方法,该方法是bean声明周期中,初始化后的后置操作,这里主要交给其子类AbstractAutoProxyCreator处理:那么我们刚刚提到,在注册BeanDefinition 的时候,会注册一个叫AnnotationAwareAspectJAutoProxyCreator的类,这个时候他就会体现出他的作用了,bean在这个类的处理下变成代理对象。
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//如果当前bean在切点pointcut表达式范围内,则获得当前bean的切面
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建代理
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
这个方法主要两个作用:
- 如果当前类在需要增强的范围内,则获取该类的切面
- 如果有切面,则创建该类的代理对象并返回
getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
那自然,获取切面的方法就是findEligibleAdvisors方法了。那这个方法重要的其实也就是两步。
- findCandidateAdvisors,找到工程所有@Aspectj注解的类封装成Advisor返回
- findAdvisorsThatCanApply,获得符合当前bean的切面,拿到所有Advisor对象后,就要遍历Advisor集合,判断当前类是否在pointcut表达式的范围中,这里进行模糊匹配,了解就好。
findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
List<Advisor> advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
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<>();
//首先获取容器中的所有bean的名称BeanName
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;
}
//判断类上是否有@Aspect注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
//创建获取有@Aspect注解类的实例工厂进行获取
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//创建切面advisor对象
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;
}
}
}
................缓存的切面aspectNames不为null但是空的,就返回空集合;
如果有缓存,就调用getAdvisors获取并加入缓存.....
return advisors;
}
其实也比较简单,无非就是遍历当前容器中所有的beanName,然后通过MetadataAwareAspectInstanceFactory实例工厂获取切面对象Advisor。
getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//1.借助工厂获取有@Aspect注解的类Class
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
//2.获取所有有@Aspect注解的类的beanName
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
//创建工厂的装饰类,获取实例只会获取一次
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
//3.循环没有@Pointcut注解的方法
for (Method method : getAdvisorMethods(aspectClass)) {
//3.1 具体获取
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()) {
//判断属性上是否有DeclareParents注解,如果有返回切面
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
该方法就是从刚刚的工厂中获取有@Aspect注解的class对象和beanName,然后遍历该类中没有@PointCut注解的类,也就是我们定义的@Around、@Before、@After等注解通知的方法,通过getAdvisor创建具体的切面类。值得注意的是getAdvisorMethods(aspectClass)方法。
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
List<Method> methods = new ArrayList();
ReflectionUtils.doWithMethods(aspectClass, (method) -> {
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
methods.sort(METHOD_COMPARATOR);
return methods;
}
这个方法所获得的是没有Pointcut注解的方法。
getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {
this.validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = this.getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
return expressionPointcut == null ? null : new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
这个方法的核心,getPointCut,顾名思义,得到pointCut。
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
} else {
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;
}
}
我们发现,最后返回了一个AspectJExpressionPointcut 对象,这个对象里面包含了我们的方法,还设置了一个属性,那么这个属性就是我们的pointCut了,那我们主要关注的方法肯定就是包含这个属性的返回aspectJAnnotation 变量的方法了。
protected static AbstractAspectJAdvisorFactory.AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
// private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class[]{Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
Class[] var1 = ASPECTJ_ANNOTATION_CLASSES;
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
Class<?> clazz = var1[var3];
AbstractAspectJAdvisorFactory.AspectJAnnotation<?> foundAnnotation = findAnnotation(method, clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
不难看出,其实就是遍历我们的增强注解,找到方法上对应的增强注解,并封装成AspectJAnnotation对象返回,那这个AspectJAnnotation对象是什么样的呢。
public AspectJAnnotation(A annotation) {
this.annotation = annotation;
//这里就是判断当前注解是啥类型,取值是枚举类:
//AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
this.annotationType = determineAnnotationType(annotation);
try {
//1. 这里就是解析注解上的value值,即pointcut值,如@Before("pointCut2()")中的pointCut2()或是具体的execution表达式
this.pointcutExpression = resolveExpression(annotation);
//2.获取注解上的参数
Object argNames = AnnotationUtils.getValue(annotation, "argNames");
this.argumentNames = (argNames instanceof String ? (String) argNames : "");
}
catch (Exception ex) {
throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
}
}
封装完成之后,返回到我们的getAdvisor当中。得到返回的AspectJExpressionPointcut对象,最后又要封装成InstantiationModelAwarePointcutAdvisorImpl对象。
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
//pointcut类及其他属性赋值
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;
//创建了Advice对象
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
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) {
//获取有@Aspect注解的类
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() + "]");
}
AbstractAspectJAdvice springAdvice;
//这里就会根据注解类型【前面说的枚举】创建不同的advice类
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
//实现了MethodInterceptor接口
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
//实现了MethodBeforeAdvice接口,没有实现MethodInterceptor接口
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
//实现了MethodInterceptor接口
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
//实现了AfterReturningAdvice接口,没有实现MethodInterceptor接口
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
//实现了MethodInterceptor接口
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);
}
//计算argNames和类型的对应关系
springAdvice.calculateArgumentBindings();
return springAdvice;
}
这里我们只要知道是根据注解的类型创建了不同的Advice类,然后返回,而几个Advice类的细节,以及有的实现的MethodInterceptor接口,有的实现的MethodBeforeAdvice接口后面会具体讲解。
到这里就对一个方法完成了全部的解析,并且构造了一个切面对象Advisor,对所有方法处理完之后,返回到buildAspectJAdvisors方法中,然后返回所拿到的这个Advisor集合。一路返回到最初的wrapIfNecessary方法中。
创建代理
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);
}
//1.创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
//设置proxyTargetClass属性
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//2. 把advice类型的增强包装成advisor切面
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//将所有切面放入代理工厂
proxyFactory.addAdvisors(advisors);
//设置目标类
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
用来控制代理工厂被配置后,是否还允许修改代理的配置,默认为false
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//3.获取代理实例
return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
this.activate();
}
return this.getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
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.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
这里就会根据注解中的ProxyTargetClass属性和目标类是否实现了接口来判断是创建Cglib代理还是JDK动态代理,注意,这里会将config,即我们的代理工厂传入具体的代理类,保存到advised中,而工厂中又保存了所有的切面对象,后面就会用到。
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
到这里代理创建完成,在调用相应的方法的时候,就会进入对应代理的invoke方法中。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
//代码1:从代理工厂中拿到TargetSource,内部保存了被代理的实例bean
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
//被代理对象的equals方法和hashCode方法不能被代理,直接走对应的方法,不走下面的切面。
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
........
Object retVal;
//设置exposeProxy属性
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//从targetSource拿到被代理实例
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//代码2:从代理工厂中拿过执行链, Object是一个被包装成MethodInterceptor类型的Advice对象
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//如果该方法没有执行链,则说明这个方法不需要被拦截,则直接反射调用
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 代码3:有调用链,就进行调用
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
这里主要做了两个工作:
- 拿到被代理类后,就通过代理工厂获取该类的调用链
- 如果如果有执行链,说明需要拦截,就进行增强调用。
先看如何拿到执行链。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//从代理工厂对象config拿到被代理类的所有切面advisors
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
//如本例的around和before两个切面
for (Advisor advisor : advisors) {
//大部分走这里
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
//通过切面的pointcut判断当前类是否需要拦截,即匹配通配符
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
//再通过pointcut判断当前方法是否需要拦截,因为我们可能只拦截部分方法
match = mm.matches(method, actualClass);
}
if (match) {//到这里类和方法都匹配,即该方法要进行拦截
//获取到切面advisor中的advice,并且包装成MethodInterceptor类型的对象
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
//处理引介切面
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
该方法主要做了如下的事:
- 匹配当前类是否和切面的pointcut匹配
- 如果匹配,则判断当前方法是否和切面pointcut匹配
- 如果都匹配,则将切面中的各种Advice包装成MethodInterceptor后添加到执行链集合返回。这里主要是为了后面调用的时候可以统一调用。
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
/*
如果是MethodInterceptor类型的,即前面创建Advice时,几个类实现了MethodInterceptor接口:
AspectJAroundAdvice
AspectJAfterAdvice
AspectJAfterThrowingAdvice
*/
if (advice instanceof MethodInterceptor) {
//包装成MethodInterceptor
interceptors.add((MethodInterceptor) advice);
}
//这里就是将没有实现MethodInterceptor接口的两个Advice: AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice包装成MethodInterceptor
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
到这里就拿到了当前方法的执行链,如果当类不需要增强,则就不会被匹配拦截,其执行链也就是空,就会直接反射执行其本身的方法,如果不为空,就需要执行代理增强的方法:
链式调用
拿到执行链之后,就会调用proceed方法进行链式调用。
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//代码1:如果执行链中的advice全部调用完毕,则直接调用joinPoint方法,即被代理的方法本身
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//interceptorsAndDynamicMethodMatchers就是刚刚获取的执行链,有当前方法需要调用的所有Advice
//代码2:这里就会按顺序调用里面的advice,然后索引加1
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
//代码3:调用MethodInterceptor中具体的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这里流程也很简单,就是按顺序取刚刚得到的调用链中的Advice,然后转成MethodInterceptor调用对应子类的invoke方法,当调用的索引和调用链集合一样大时,说明所有的Advice都调用完成了,这时就可以执行被代理的方法。
那么有个问题,这里没有for循环,是如何调用多次的呢?其实很简单,已经说了是链式调用,因此调用完上一个Advice后,会在上一个invoke中的最后再调用proceed方法,这时就开始了下一次Advice的调用。
Advice有多个子类,分别对应Before、Around、AfterRturning、AfterThrowing、After等注解增强。
其首先会调用Around注解方法:
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
//反射调用Around注解中的方法
return invokeAdviceMethod(pjp, jpm, null, null);
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
}
这就执行了文章一开始写的Demo中的System.out.println(“around的前置通知”);,然后走到Object proceed = point.proceed();又会回到proceed方法,继续调用,接着就会调用@Before注解的方法,执行System.out.println(“before前置通知”);,之后又会调用proceed()继续上面的流程片【如下】。这时全部Advice已经调用完毕,就会执行被代理的方法,执行System.out.println(“saveAccount…”);,然后从@Around的proceed()返回执行System.out.println(“around的后置通知”);结束调用。
//MethodBeforeAdviceInterceptor #invoke
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
但是@AfterReturning这种需要在被代理方法执行后再执行的Adivice怎么办呢?看一下吧:
//AfterReturningAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
其实,如果调用到该方法,则执行再次进入proceed方法,其实就相当于@Around中的proceed方法的作用,等全部执行完后,再执行后置通知。对应@AfterThrowing是一样的道理,只是将proceed放入了try中,在finally中会判断是否发生异常,如果发生异常,就执行@AfterThrowing注解的方法。