<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