测试项目已上传到码云,可以下载:https://gitee.com/yangxioahui/aopdemo.git
具体如下:
public interface Calc { Integer add(int num1,int num2); }
//目标是对add 方法进行切入 @Component public class MyMath implements Calc { public Integer add(int num1,int num2){ return num1+num2; } } @Aspect @Component public class MyAspectJ { @Pointcut(" execution(* com.yang.xiao.hui.aop.MyMath.*(..))") private void pointcut(){} @Before(value = "pointcut()") public void before(JoinPoint joinPoint){ System.out.println("before。。。。。"); } @After(value = "pointcut()") public void after(JoinPoint joinPoint){ System.out.println("after。。。。"); } @AfterReturning(value = "pointcut()") public void afterReturning(){ System.out.println("afterReturning。。。"); } @AfterThrowing(value = "pointcut()") public void afterThrowing(JoinPoint joinPoint){ System.out.println("afterThrowing。。。。"); } @Around(value ="pointcut()") public void around(ProceedingJoinPoint joinPoint){ System.out.println("around-before。。。。"); try { Object proceed = joinPoint.proceed(); System.out.println("around-after_return。。。"); } catch (Throwable throwable) { System.out.println("around-throw。。。"+throwable.getMessage()); } System.out.println("around-after。。。"); } } //测试类 @Configuration @ComponentScan("com.yang.xiao.hui.aop") @EnableAspectJAutoProxy(exposeProxy = true) public class App { public static void main( String[] args ) { ApplicationContext ctx = new AnnotationConfigApplicationContext(App.class); Calc myMath = (Calc)ctx.getBean("myMath"); myMath.add(3,5); System.out.println(ctx.getBean("myMath").getClass()); } }
启动项目结果:
至此,测试环境搭建完毕
原理分析:
我们要对MyMath 类的add 方法进行前后代理,我们也可以自己实现:
我们实现的叫静态代理,如果是程序实现的叫动态代理;切入的方式有前置切入,后置切入等,切入点有切入表达式(Pointcut),在java中,一切皆对象,spring将各种切入方式叫做Advice(增强器),如BeforeAdvice,而我们是通过方法切入
所以又叫MethodBeforeAdvice:
单有一个Advice 我们并不知道要给哪个类进行切入,因此还需要切入点,于是我们将Advice和切入点Pointcut 结合一起组成一个Advisor:
例如:DefaultPointcutAdvisor它的构造器:
一个被切入的类,它的代理类,会有很多个Advisor,那么我们称这个代理类叫做Advised:
至此,我们知道了advice ,advisor 和advised的三者之间的关系了:
下面的我们要解决的问题是:1.各种切入方式是如何被封装成advisor的 2 如何知道某个类是否需要被代理 3. 如何创建代理类 4 类被代理后,目标方法是如何执行的:
先来看一个注解:@EnableAspectJAutoProxy()
点击进入该注解:
我们继续跟进,看看到底向容器注册的是哪个bean;
我们再看看注解信息是怎么保存到注册器中的;
小结:@EnableAspectJAutoProxy 注解最终向容器中注入了一个 bean---- AnnotationAwareAspectJAutoProxyCreator,因此我们问题的答案都可以在这个bean找到,那么我们看看其继承体系:
可见,AnnotationAwareAspectJAutoProxyCreator是一个beanPostProcessor,也就是后置处理器,会在bean的不同生命周期里其作用:
因此,这些生命周期里,会进行代理对象的创建:
我们debug 调试容器创建过程:
省略n步骤:
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; //首次进来,这个为null 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); //容器中获取所有的beanName,因为Object可以代表所有的类型 for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { //isEligibleBean(beanName)这个基本返回true 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)) { //判断类有没@Aspect注解,而我们定义的MyAspectJ是有该注解的 aspectNames.add(beanName);//切面类可能有多个,我本次测试写了一个MyAspectJ AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { //如果我们的MyMyAspectJ是单例的话,条件成立,显然,我们的就是单例 MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); //获取一个切面工厂 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);//这里获取了我们要的advisor,所以稍后要分析 if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); //如果是单例就缓存起来,下次就不用再次获取了 } else { this.aspectFactoryCache.put(beanName, factory);//非单例就缓存工厂 } advisors.addAll(classAdvisors);//收集所有的advisor } 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); //单例的切面类,从缓存中就可以取到他们所有的advisor } else { MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); advisors.addAll(this.advisorFactory.getAdvisors(factory)); //非单例的切面类,从工厂中去处 } } return advisors; }
//通过上面分析:最终会通过调用advisorFactory.getAdvisors(factory)获取到advisor,继续跟进:
@Override public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); //获取切面类,在这里就是我们的com.yang.xiao.hui.aop.MyAspectJ String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();//获取类名,这里是myAspectJ validate(aspectClass);//这里主要校验切面类的父类有没@Aspect注解,如果有,必须是抽象类,其次会校验切面类有没@Aspect注解 // 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)) { //通过切面类,获取所有的方法,方法不包含含有@Pointcut注解的方法,因为带有该注解的方法为切入点 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); //这里将方法封装成了Advisor,后续会跟踪 if (advisor != null) { //并不是所有方法,都能封装成advisor的,只有含有@before,@after等注解的方法才会被封装 advisors.add(advisor); } } // If it's a per target aspect, emit the dummy instantiating aspect. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { //懒加载相关的,会增加一个advisor,显然我们的不是 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; }
根据上面分析,切面类的方法最终转成advisor,是调用了 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);我们跟进去:
@Override @Nullable public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); //校验切面类的父类有没@Aspect注解,如果有,必须是抽象类,其次会校验切面类有没@Aspect注解 AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); //里面会校验candidateAdviceMethod方法是否有@Before @After等注解 if (expressionPointcut == null) { return null; } return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); //这个就是我们要找的advisor,expressionPointcut含有pointcut和advice
}
我们分析下: AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); 方法:
@Nullable 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()); //这里将@before/@After等注解的切入点表达式存起来了 if (this.beanFactory != null) { ajexp.setBeanFactory(this.beanFactory); } return ajexp; }
@Nullable protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) { //查询某个方法是否有aspectj相关注解 for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) { //ASPECTJ_ANNOTATION_CLASSES //相关注解类如下图: AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz); if (foundAnnotation != null) { return foundAnnotation; } } return null; }
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(); //增强的方法名@before等注解标注的类 this.parameterTypes = aspectJAdviceMethod.getParameterTypes();//advice方法的参数类型 this.aspectJAdviceMethod = aspectJAdviceMethod;//advice方法,@before等注解标注的方法 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);//创建一个advice } }
我们看看advice的创建过程:
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); }
@Override @Nullable 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);//校验增强方法是否含有@before等相关注解 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)) { //这里又一次校验有没@Aspect注解 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()) { //根据注解的类型创建对应的advice case AtPointcut: //如果是切入点,其实就不用创建advice了 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; }
通过advice的创建过程,我们知道,一个advice主要包含增强的方法,方法参数,以及切入点,而advisor是包含Advice的,并且属性更多,功能更强大
至此,我们的第一个问题解决了:各种切入方式是如何被封装成advisor的?
小结:AnnotationAwareAspectJAutoProxyCreator这个类实现了InstantiationAwareBeanPostProcessor接口,所以其中有个方法:Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
在其他bean创建的过程中,会调用该方法,该方法会去查找容器中所有的advisor,查找的思路是获取所有的Bean的名称,然后通过名称获取bean的类型(此时bean还没实例化,所以取得是类型),之后判断有没@Aspect注解如果有该注解的话,就判断类下面的方法有没Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 这几个注解,有就将对应的方法封装成advice,进一步封装成advisor
至此,所有的切入方法都封装成了advisor,存到了一个list集合中,下面分析代理类的创建,也就是我们的MyMath被代理过程:debug调试其创建bean的过程
前面分析过: AnnotationAwareAspectJAutoProxyCreator 实现BeanPostProcessor接口,该接口有2个方法:
我们先看看postProcessBeforeInitialization 的代码:
可见,没做任何逻辑,我们再看看另外一个方法:postProcessAfterInitialization
所以我们断点在该方法,调试MyMath创建过程:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { //在postProcessBeforeInstantiation方法也有创建代理对象逻辑,如果在那个方法创建的代理对象会存到targetSourcedBeans return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { //advisedBeans 缓存中已经有该bean,并且不用增强 return bean; }
//InfrastructureClass 是指Advice,Pointcut,Advisor,AopInfrastructureBean; shouldSkip(bean.getClass(), beanName)指的是beanName以 “.ORIGINAL” 结尾的
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { 在postProcessBeforeInstantiation这个方法也有一样的逻辑 this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); //获取能用在该类上的advisor,逻辑是根据切面表达式来判断,之后会分析 if (specificInterceptors != DO_NOT_PROXY) { //如果获取到的advisor不为空,也就是由advisor可以用在该类上就创建代理对象 this.advisedBeans.put(cacheKey, Boolean.TRUE); //设置缓存,说明该bean的创建需要代理 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); //创建代理对象 this.proxyTypes.put(cacheKey, proxy.getClass());//缓存代理对象的类 return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); //如果没有可用的增强器,就标注上该bean不用创建代理 return bean; }
//上面要关注的2个方法,一个是如何查找一个类的增强器,也就是advisor,第二个是代理对象的创建:
先看这个方法:Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); //获取所有的advisor,这个在之前已经分析过了 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//拿到所有的advisor,看看哪些能用在指定的bean,下面会跟进分析 extendAdvisors(eligibleAdvisors); //而外加入了一个advisor: advisors.add(0, ExposeInvocationInterceptor.ADVISOR); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); //排序 } return eligibleAdvisors; }
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); //继续跟进该方法 } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { //如果没有候选的advisor,就不用走下去了 return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {//前面分析过,我们的advisor类型是:InstantiationModelAwarePointcutAdvisor 所以不会进入下面逻辑 eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) {//前面分析过,我们的advisor类型是:InstantiationModelAwarePointcutAdvisor 所以不会进入下面逻辑 // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { //最终会到达这里,所以canApply(candidate, clazz, hasIntroductions) 决定了该advisor能否用于指定的class eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
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; } }
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { //判断切入点过滤的类型能否跟指定的类匹配,例如切入点表达式指定的是A类型,那么只有A类型才符合 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; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<>(); if (!Proxy.isProxyClass(targetClass)) { //如果目标class不是Proxy的子类 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; //判断是否有方法匹配了,只要有一个方法匹配上切入点表达式,对应的advisor就可以用在目标class上 } } } return false; }
至此,我们知道了给目标class获取advisor的原理: 获取所有的advisor,然后遍历,根据advisor的切入点表达式Pointcut,校验目标class的方法是否有匹配上advisor的
接着,我们分析代理对象的创建过程:
Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); //创建代理对象
目标bean被封装成了一个SingletonTargetSource
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
//这里给bean的定义设置了一个属性originalTargetClass AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory();//代理工厂 proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { //@EnableAspectJAutoProxy 注解的proxyTargetClass属性,当为true时,就不支持jdk动态代理,全部使用cglib,默认是false if (shouldProxyTargetClass(beanClass, beanName)) { //判断bean的定义对象的属性preserveTargetClass 是否为true,为true时,只支持cglib proxyFactory.setProxyTargetClass(true); } else {
//判断beanClass所有的实现接口,排除InitializingBean,AutoCloseable,DisposableBean,Closeable,Aware,是否还有其他接口,是的话,就可以用jdk动态代理 evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);//主要的功能是强转,因为specificInterceptors数组的类型是Object proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory);//目前空实现 proxyFactory.setFrozen(this.freezeProxy); //设置是否需要冻结代理相关的配置,false if (advisorsPreFiltered()) { //advisor是否是过滤过的了,根据前面分析,advisor用于指定的bean前,通过切入点表达式过滤过了 proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
//上面只是为需要代理的bean,创建了一个代理工厂,并且代理工厂设置了advisors 和目标bean对象,接下来跟进代理对象创建:
先分析: createAopProxy()
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { //前面ProxyFactory 设置的目标对象,advisors 都存在AdvisedSupport这里了 @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 源码对 config.isOptimize()解释:optimization will usually mean that advice changes won't take effect after a proxy has been created.
//config.isOptimize()默认是false,config.isProxyTargetClass这个是@EnableAspectJAutoProxy的属性,为true时,即使目标类实现了接口也用cglib代理
//hasNoUserSuppliedProxyInterfaces(config) 没有用户提供的接口时,也没法使用jdk动态代理
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)) { //如果目标类就是接口,或者其继承了Proxy类,那就没法使用cglib代理了 return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); //使用cglib代理 } else { return new JdkDynamicAopProxy(config); //使用jdk代理 } }
... 省略其他代码
}
由于我的是jdk动态代理,执行getProxy后:
我们看看获取接口的方法:
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) { //主要是加上了三个接口SpringProxy,Advised,DecoratingProxy Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces(); if (specifiedInterfaces.length == 0) { // No user-specified interfaces: check whether target class is an interface. Class<?> targetClass = advised.getTargetClass(); if (targetClass != null) { if (targetClass.isInterface()) { advised.setInterfaces(targetClass); } else if (Proxy.isProxyClass(targetClass)) { advised.setInterfaces(targetClass.getInterfaces()); } specifiedInterfaces = advised.getProxiedInterfaces(); } } boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class); boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class); boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)); int nonUserIfcCount = 0; if (addSpringProxy) { nonUserIfcCount++; } if (addAdvised) { nonUserIfcCount++; } if (addDecoratingProxy) { nonUserIfcCount++; } Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount]; System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length); int index = specifiedInterfaces.length; if (addSpringProxy) { proxiedInterfaces[index] = SpringProxy.class; index++; } if (addAdvised) { proxiedInterfaces[index] = Advised.class; index++; } if (addDecoratingProxy) { proxiedInterfaces[index] = DecoratingProxy.class; } return proxiedInterfaces; }
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 这个是jdk源码的内容了
至此,spring创建代理对象的源码分析完毕了,我们看看cglib的getProxy方法:
@Override public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource()); } try { Class<?> rootClass = this.advised.getTargetClass(); //因为cglib使用的继承方式,所以目标类就是父类 Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { //判断目标类是否已经是cglib的代理类了,cglib的代理类,beanName是以"$$" 结尾的 proxySuperClass = rootClass.getSuperclass(); 如果是的话,就代理目标类的父类 Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } // Validate the class, writing log messages as necessary. 做一些日志打印 validateClassIfNecessary(proxySuperClass, classLoader); // Configure CGLIB Enhancer... Enhancer enhancer = createEnhancer(); //cglib的创建器,相当于jdk动态代理的代理工厂Proxy if (classLoader != null) { enhancer.setClassLoader(classLoader); //设置类加载器 if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } enhancer.setSuperclass(proxySuperClass); //设置需要代理的类 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); //跟jdk代理一样,这里也会新增三个接口SpringProxy,Advised,DecoratingProxy enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);//cglib代理对象的命名策略,会加上"$$" 和 BySpringCGLIB 这些字符 enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // fixedInterceptorMap only populated at this point, after getCallbacks call above enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // Generate the proxy class and create a proxy instance. return createProxyClassAndInstance(enhancer, callbacks);//最终会调用该方法创建一个代理对象 } catch (CodeGenerationException | IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class", ex); } catch (Throwable ex) { // TargetSource.getTarget() failed throw new AopConfigException("Unexpected AOP exception", ex); } }
@Override protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) { Class<?> proxyClass = enhancer.createClass(); //创建出代理类 Object proxyInstance = null; if (objenesis.isWorthTrying()) { try { proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache()); //创建代理实例 } catch (Throwable ex) { logger.debug("Unable to instantiate proxy using Objenesis, " + "falling back to regular proxy construction", ex); } } if (proxyInstance == null) { // Regular instantiation via default constructor... try { Constructor<?> ctor = (this.constructorArgs != null ? proxyClass.getDeclaredConstructor(this.constructorArgTypes) : proxyClass.getDeclaredConstructor()); ReflectionUtils.makeAccessible(ctor); proxyInstance = (this.constructorArgs != null ? ctor.newInstance(this.constructorArgs) : ctor.newInstance()); //通过构造器创建代理实例 } catch (Throwable ex) { throw new AopConfigException("Unable to instantiate proxy using Objenesis, " + "and regular proxy instantiation via default constructor fails as well", ex); } } ((Factory) proxyInstance).setCallbacks(callbacks); return proxyInstance; }
我们可以输出代理类的字节码,设置一个属性:System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
执行后,在类路径可以看到:
找到我们的目标类:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.sun.proxy; import com.yang.xiao.hui.aop.Calc; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; import org.aopalliance.aop.Advice; import org.springframework.aop.Advisor; import org.springframework.aop.SpringProxy; import org.springframework.aop.TargetSource; import org.springframework.aop.framework.Advised; import org.springframework.aop.framework.AopConfigException; import org.springframework.core.DecoratingProxy; //代理对象的所有方法的调用最终都会交给InvocationHandler 的invoke方法执行 public final class $Proxy22 extends Proxy implements Calc, SpringProxy, Advised, DecoratingProxy { // SpringProxy, Advised, DecoratingProxy 这三个接口是后面加上的,前面分析过了 private static Method m1; private static Method m9; private static Method m14; private static Method m13; private static Method m19; private static Method m24; private static Method m4; private static Method m8; private static Method m17; private static Method m18; private static Method m0; private static Method m23; private static Method m16; private static Method m11; private static Method m7; private static Method m2; private static Method m26; private static Method m15; private static Method m27; private static Method m20; private static Method m5; private static Method m6; private static Method m21; private static Method m10; private static Method m3; private static Method m25; private static Method m12; private static Method m22; public $Proxy22(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final boolean isExposeProxy() throws { try { return (Boolean)super.h.invoke(this, m9, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void addAdvisor(Advisor var1) throws AopConfigException { try { super.h.invoke(this, m14, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final boolean isProxyTargetClass() throws { try { return (Boolean)super.h.invoke(this, m13, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void removeAdvisor(int var1) throws AopConfigException { try { super.h.invoke(this, m19, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final Class[] getProxiedInterfaces() throws { try { return (Class[])super.h.invoke(this, m24, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int indexOf(Advisor var1) throws { try { return (Integer)super.h.invoke(this, m4, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final TargetSource getTargetSource() throws { try { return (TargetSource)super.h.invoke(this, m8, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void addAdvice(int var1, Advice var2) throws AopConfigException { try { super.h.invoke(this, m17, new Object[]{var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final void addAdvice(Advice var1) throws AopConfigException { try { super.h.invoke(this, m18, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final boolean isInterfaceProxied(Class var1) throws { try { return (Boolean)super.h.invoke(this, m23, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final boolean removeAdvice(Advice var1) throws { try { return (Boolean)super.h.invoke(this, m16, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final void setExposeProxy(boolean var1) throws { try { super.h.invoke(this, m11, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final void setTargetSource(TargetSource var1) throws { try { super.h.invoke(this, m7, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final Class getTargetClass() throws { try { return (Class)super.h.invoke(this, m26, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void addAdvisor(int var1, Advisor var2) throws AopConfigException { try { super.h.invoke(this, m15, new Object[]{var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final Class getDecoratedClass() throws { try { return (Class)super.h.invoke(this, m27, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final boolean removeAdvisor(Advisor var1) throws { try { return (Boolean)super.h.invoke(this, m20, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final int indexOf(Advice var1) throws { try { return (Integer)super.h.invoke(this, m5, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final boolean isFrozen() throws { try { return (Boolean)super.h.invoke(this, m6, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final boolean replaceAdvisor(Advisor var1, Advisor var2) throws AopConfigException { try { return (Boolean)super.h.invoke(this, m21, new Object[]{var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final void setPreFiltered(boolean var1) throws { try { super.h.invoke(this, m10, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final Integer add(int var1, int var2) throws { try { return (Integer)super.h.invoke(this, m3, new Object[]{var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final String toProxyConfigString() throws { try { return (String)super.h.invoke(this, m25, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final Advisor[] getAdvisors() throws { try { return (Advisor[])super.h.invoke(this, m12, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final boolean isPreFiltered() throws { try { return (Boolean)super.h.invoke(this, m22, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m9 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isExposeProxy"); m14 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor", Class.forName("org.springframework.aop.Advisor")); m13 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isProxyTargetClass"); m19 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor", Integer.TYPE); m24 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getProxiedInterfaces"); m4 = Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf", Class.forName("org.springframework.aop.Advisor")); m8 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetSource"); m17 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice", Integer.TYPE, Class.forName("org.aopalliance.aop.Advice")); m18 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice", Class.forName("org.aopalliance.aop.Advice")); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); m23 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isInterfaceProxied", Class.forName("java.lang.Class")); m16 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvice", Class.forName("org.aopalliance.aop.Advice")); m11 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setExposeProxy", Boolean.TYPE); m7 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setTargetSource", Class.forName("org.springframework.aop.TargetSource")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m26 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetClass"); m15 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor", Integer.TYPE, Class.forName("org.springframework.aop.Advisor")); m27 = Class.forName("org.springframework.core.DecoratingProxy").getMethod("getDecoratedClass"); m20 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor", Class.forName("org.springframework.aop.Advisor")); m5 = Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf", Class.forName("org.aopalliance.aop.Advice")); m6 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isFrozen"); m21 = Class.forName("org.springframework.aop.framework.Advised").getMethod("replaceAdvisor", Class.forName("org.springframework.aop.Advisor"), Class.forName("org.springframework.aop.Advisor")); m10 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setPreFiltered", Boolean.TYPE); m3 = Class.forName("com.yang.xiao.hui.aop.Calc").getMethod("add", Integer.TYPE, Integer.TYPE); m25 = Class.forName("org.springframework.aop.framework.Advised").getMethod("toProxyConfigString"); m12 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getAdvisors"); m22 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isPreFiltered"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
//通过分析,我们知道,jdk动态代理类的所有方法,都会交给//代理对象的所有方法的调用最终都会交给InvocationHandler 的invoke方法执行,那么这个InvocationHandler 又是哪里来的呢,我们回到jdk动态代理创建过程:
因此代理类的方法会被JdkDynamicAopProxy 的invoke 拦截,而JdkDynamicAopProxy有个属性:AdvisedSupport 该对象拥有被代理对象和advisors,因此可以进行前后拦截了,而AdvisedSupport 是什么时候传入的呢?
至此,哪个类会被代理,以及如何代理,分析完毕,下篇博客,我们会分析,代理方法的执行流程