<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.1.5.RELEASE</version> </dependency>
@Before @After @AfterReturning @AfterThrowing @Around
@EnableAspectJAutoProxy
@Configuration @ComponentScan(value = {"cn.tedu.demo"}) @EnableAsync @EnableAspectJAutoProxy public class FirstConfig{}
/** * 切面,使用@Aspect标注 */ @Component @Aspect public class CustomAspect{ /** * 使用@PointCut定义切入点 */ @Pointcut(value = "execution(* cn.tedu.demo.aspect.AspectInvok.invok(..))") public void pointCut(){} /** * 前置通知,在指定方法之前执行 * @param point JoinPoint对象,可以获取切点的各种属性,比如入参的参数等 */ @Before(value = "pointCut()") public void before(JoinPoint point){ //获取入参的参数的值 Object[] args = point.getArgs(); System.out.println(Arrays.asList(args)); //获取MethodSignature,其中可以获取切点的各种属性,比如方法返回类型,参数等等 MethodSignature signature = (MethodSignature) point.getSignature(); String[] parameterNames = signature.getParameterNames(); System.out.println(Arrays.asList(parameterNames)); System.out.println("在方法之前执行"); } /** * 在切点之后执行 * @param point JoinPoint对象 */ @After(value = "pointCut()",argNames = "point") public void after(JoinPoint point){ System.out.println("在方法之后执行"); } /** * 在方法前后都会执行 * @param point */ @Around(value = "pointCut()") public void around(ProceedingJoinPoint point)throws Throwable { System.out.println("前置执行"); //执行方法,可以获取返回值,否则方法将不会执行 Object result = point.proceed(point.getArgs()); System.out.println("后置执行,执行的结果=="+result); } /** * 正常返回通知, * @param point Joinpoint对象 * @param result 方法执行返回的结果,需要和@AfterReturning注解中returning中的属性值相同,否则不能自动装配 */ @AfterReturning(value = "pointCut()",returning = "result") public void afterReturning(JoinPoint point,Object result){ System.out.println("正常返回执行,执行的结果为:"+result); } /** * 异常返回执行,程序出现异常了才会执行 * @param point * @param ex 切入点执行抛出的异常,需要和@AfterThrowing注解的throwing值相同,否则不能完成自动装配 */ @AfterThrowing(value = "pointCut()",throwing = "ex") public void afterThrowing(JoinPoint point,Exception ex){ System.out.println("异常返回执行,执行的异常为:"+ex); } }
定义一个注解,如下:
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyAnnotation { Stringname()default "陈加兵"; int age()default 22; }
定义一个切面,使用注解如下:
@Component @Aspect public class CustomAspect{ /** * 使用@PointCut定义切入点 */ @Pointcut(value = "@annotation(cn.tedu.demo.aspect.MyAnnotation)") public void pointCut(){} /** * 前置通知,在指定方法之前执行 * @param point JoinPoint对象,可以获取切点的各种属性,比如入参的参数等 */ @Before(value = "pointCut()") public void before(JoinPoint point){ //获取MethodSignature,其中可以获取切点的各种属性,比如方法返回类型,参数等等 MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); //获取方法上指定的注解 MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class); System.out.println("name="+myAnnotation.name()); System.out.println("在方法之前执行"); } }
@EnableAspectJAutoProxy
该注解中可以看出使用了 @Import(AspectJAutoProxyRegistrar.class)
,因此实际作用的类就是 AspectJAutoProxyRegistrar
,因此我们必须跟进源码去看。 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy {
ImportBeanDefinitionRegistrar AnnotationAutoProxyCreator
class AspectJAutoProxyRegistrarimplements ImportBeanDefinitionRegistrar{ /** * 向容器中注入AnnotationAutoProxyCreator */ @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //调用方法注册AnnotationAutoProxyCreator AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); //获取@EnableAspectJAutoProxy注解中两个属性的值 AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); //判断注解属性的值 if (enableAspectJAutoProxy != null) { if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } }
Map<Object, Boolean>
@EnableAspectJAutoProxy
注解的主要作用就是向容器中注入 AnnotationAutoProxyCreator
,ID为 org.springframework.aop.config.internalAutoProxyCreator
,因此切面的关键类就是这个,我们看看继承关系图,如下:
InstantiationAwareBeanPostProcessor BeanFactoryAware
AnnotationAutoProxyCreator
这个Bean的初始化和实例化前后执行逻辑,无非就是上面两个接口定义的方法,我们可以在对应的方法中打断点跟踪代码。 刷新容器种执行 registerBeanPostProcessors(beanFactory)
方法将全部的后置处理器注入到容器中,在其中执行执行后续的setBeanFactory的方法
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#setBeanFactory
AspectJAdvisorFactory
:顾名思义,当然是从标注 @Aspect的类中
创建增强器【切面增强的方法】 BeanFactoryAspectJAdvisorsBuilder
:简单的说就是创建增强器的辅助类,用来构造增强器 @Override public void setBeanFactory(BeanFactory beanFactory){ //调用父类的方法 super.setBeanFactory(beanFactory); if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { throw new IllegalArgumentException( "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory); } //实际执行的是initBeanFactory initBeanFactory((ConfigurableListableBeanFactory) beanFactory); } /*******************************initBeanFactory**************************/ @Override protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory){ super.initBeanFactory(beanFactory); //创建切面增强器工厂 if (this.aspectJAdvisorFactory == null) { this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory); } //创建切面增强生成器 this.aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory); }
刷新容器方法中执行 finishBeanFactoryInitialization(beanFactory)
【实例化剩余的单例Bean】
getBean()—>doGetBean—>createBean,在createBean方法中执行 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
【在实例化之前给一个机会返回一个代理】
内部执行 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
内部循环遍历后置处理器,判断类型为 InstantiationAwareBeanPostProcessor
,执行 postProcessBeforeInstantiation()
方法【在实例化之前调用,接口定义】。
此时执行到 AbstractAutoProxyCreator#postProcessBeforeInstantiation
,源码如下:
/** * 在实例化之前执行逻辑,如果返回不为null,后续的属性赋值等操作将不会执行 * 主要的作用 */ public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName){ //获取cacheKey,主要是和FactoryBean对象区别 Object cacheKey = getCacheKey(beanClass, beanName); //beanName为空,或者targetSourcedBeans不包含当前Bean if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { //如果需要增强的Bean已经包含了当前Bean,后续流程不需要执行,返回null即可 if (this.advisedBeans.containsKey(cacheKey)) { return null; } /**isInfrastructureClass(beanClass):【如果当前Bean是基础的类【实现了Advice、Pointcut、Advisor、AopInfrastructureBean】并且满足this.aspectJAdvisorFactory不为null&&当前类被@Aspect注解标注了】 *shouldSkip(beanClass, beanName): * ①获取所有的候选的增强器【List<Advisor> candidateAdvisors = findCandidateAdvisors();】 * ②循环候选增强器,判断类型是否是AspectJPointcutAdvisor */ if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { //如果满足条件,那么表示该类是一个切面,不是需要增强的Bean,设置value为false this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } //获取自定义的TargetSource TargetSource targetSource = getCustomTargetSource(beanClass, beanName); //如果存在,那么可以直接创建代理对象 if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }
代码继续执行,发现 postProcessProperties
、 postProcessBeforeInitialization
、 postProcessBeforeInitialization
都是默认的实现,这里跳过。
postProcessAfterInitialization
中,逻辑如下:
wrapIfNecessary(bean, beanName, cacheKey)
方法,封装Bean,其实就是创建代理对象 wrapIfNecessary
方法
specificInterceptors
,代码跟进,最重要的实现是在 org.springframework.aop.support.AopUtils.canApply(org.springframework.aop.Advisor, java.lang.Class<?>, boolean)
这个方法中,大致的思想就是 Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean))
createProxy
方法
evaluateProxyInterfaces(beanClass, proxyFactory);
方法,主要的作用就是检查当前Bean实现的接口是否符合要求能够创建代理对象【不能是 InitializingBean
, DisposableBean
, Closeable
, AutoCloseable
等接口】,如果满足直接设置到ProxyFactory中,否则设置 proxyTargetClass=true
【直接代理目标类targetSource】 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors)
方法,将公共的拦截器和适配的拦截器 specificInterceptors
一起返回
this.interceptorNames
拦截器名称从容器中获取Bean,将其解析成 commonInterceptors
proxyFactory.getProxy(getProxyClassLoader())
方法,获取代理对象
org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy
的方法创建代理对象,是AopProxyFactory默认实现类中的方法,具体逻辑如下:
proxyTypes
中,返回proxy