文章目录

  • 前言
  • 一、AnnotationAwareAspectJAutoProxyCreator后置处理器的创建
  • 二、在AnnotationAwareAspectJAutoProxyCreator后置处理器方法中创建代理(jdk或cglib)
  • 2.1、创建CglibAopProxy或JdkDynamicAopProxy对象
  • 2.2、 执行代理方法
  • 三、springaop代理类创建过程
  • 四、springAop代理类执行过程
  • 五、springAop后置处理器查找advisor过程
  • 六、自己实现一个aop注解
  • 1、advisor
  • 2、advice
  • 3、pointcut
  • 4、ClassFilter
  • 5、MethodMatcher
  • 七、DeclareParents注解的使用
  • 六、使用JdkDynamicAopProxy
  • 总结



前言

暂无

一、AnnotationAwareAspectJAutoProxyCreator后置处理器的创建

spring.factories内配置的自动配置类AopAutoConfiguration,类上ConditionalOnClass注解内容EnableAspectJAutoProxy注解,EnableAspectJAutoProxy注解上方@Import导入了AspectJAutoProxyRegistrar类,为ImportBeanDefinitionRegistrar接口的实现类。在CongifurationClassParser解析@Import注解时调用ImportBeanDefinitionRegistrar接口的方法,AnnotationAwareAspectJAutoProxyCreator的beanDefinition会被注册到spring

二、在AnnotationAwareAspectJAutoProxyCreator后置处理器方法中创建代理(jdk或cglib)

2.1、创建CglibAopProxy或JdkDynamicAopProxy对象

AnnotationAwareAspectJAutoProxyCreator间接实现了SmartInstantiationAwareBeanPostProcessor接口,所以在bean创建完成后会调用其后置处理方法,在后置处理器方法中使用ProxyFactory(extends ProxyCreatorSupport).getProxy()来创建代理,在ProxyFactory的父类ProxyCreatorSupport默认构造函数里new DefaultAopProxyFactory();调用DefaultAopProxyFactory的createAopProxy方法,返回CglibAopProxy或JdkDynamicAopProxy对象,

AbstractAutoProxyCreator创建ProxyFactory时候,为ProxyFactory设置Advisor实现类(包装了Advice(AspectJAroundAdvice)和pointcut)

2.2、 执行代理方法

CglibAopProxy在getProxy创建代理类的时候,设置了DynamicAdvisedInterceptor回调,调用回调的intercept方法时,new CglibMethodInvocation,调用其proceed方法。

ReflectiveMethodInvocation.proceed---->AspectJAroundAdvice.invoke,ProceedingJoinPoint作为@Around方法的参数,其实是将ReflectiveMethodInvocation包装到了ProceedingJoinPoint实现类里面,调用ProceedingJoinPoint.proceed实际上是调用ReflectiveMethodInvocation.proceed,当创建的代理类的拦截器都执行完以后就执行默认的@Around修饰的方法。

三、springaop代理类创建过程

spring 多个aop执行顺序 spring aop执行过程_ide

四、springAop代理类执行过程

spring 多个aop执行顺序 spring aop执行过程_spring 多个aop执行顺序_02

五、springAop后置处理器查找advisor过程

spring 多个aop执行顺序 spring aop执行过程_ide_03

六、自己实现一个aop注解

1、advisor

public class MyAopAspectjAdvisor implements PointcutAdvisor {

    private Pointcut pointcut = new MyAopAspectJPointcut();

    private Advice advice = new MyAopAspectjAdvice();

    @Override
    public Pointcut getPointcut() {
        return this.pointcut;
    }

    @Override
    public Advice getAdvice() {
        return this.advice;
    }

    @Override
    public boolean isPerInstance() {
        return true;
    }

    public void setPointcut(Pointcut pointcut) {
        this.pointcut = pointcut;
    }

    public void setAdvice(Advice advice) {
        this.advice = advice;
    }
}

2、advice

public class MyAopAspectjAdvice implements MethodInterceptor {
    private static final Logger log = LoggerFactory.getLogger(MyAopAspectjAdvice.class);
    public MyAopAspectjAdvice(){
    }
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        log.info("-------------------------------------------------------------------自定义增强器");
        return invocation.proceed();
    }
}

3、pointcut

public class MyAopAspectJPointcut implements Pointcut {
    @Override
    public ClassFilter getClassFilter() {
        return ClassFilter.TRUE;
    }

    @Override
    public MethodMatcher getMethodMatcher() {
        return new MyAopMethodMatcher();
    }
}

4、ClassFilter

这里使用默认的ClassFilter,ClassFilter.TRUE

5、MethodMatcher

public class MyAopMethodMatcher implements MethodMatcher {
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        Proxy annotation = AnnotationUtils.findAnnotation(method, Proxy.class);
        return annotation != null && annotation.isProxy();
    }

    @Override
    public boolean isRuntime() {
        return false;
    }

    @Override
    public boolean matches(Method method, Class<?> targetClass, Object... args) {
        return false;
    }
}

七、DeclareParents注解的使用

DeclareParents和pointcut一样也会为表达式匹配的类生成代理,会为匹配的类增加一个接口实现,

真正调用这个接口的实现是注解里声明的defaultImpl实现类对应的方法。(DeclareParentsAdvisor)

@Aspect
@Component
public class ProxyTestConfig {
    
    @DeclareParents(value = "com.springboot.service.*", defaultImpl = TestDeclareParentImpl.class)
    private ITestDeclareParent testDeclareParent;

    @Pointcut("execution(* com.springboot.service..*.*(..))")
    public void around() {
    }

    @Around("around()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("around start......");
        return joinPoint.proceed();
    }
}

public interface ITestDeclareParent {
    String hello();
}

// 并不需要放入spring容器
public class TestDeclareParentImpl implements ITestDeclareParent{
    @Override
    public String hello(){
        System.out.println("===============================================================");
        return "zs";
    }
}

@RunWith(SpringRunner.class)
@SpringBootTest(classes={SpringBootStarterApplication.class})
public class SpringbootTest {

    @Autowired
    private IProxyTestService IProxyTestService;

    @Test
    public void testProxy() {
        ((ITestDeclareParent)IProxyTestService).hello();
    }
}

六、使用JdkDynamicAopProxy

在new ProxyFactory时候将实现了接口的类传入即可

注意:当直接传入advice时,proxyFactory会将advice包装到DefaultPointcutAdvisor类中,new DefaultPointcutAdvisor(advice),

而这个类内部的pointcut不管ClassFilter还是MethodMatcher,其matches方法都默认返回true,即对所有的类的所有方法都进行代理。

这个advice对每个类都进行调用。

public void testProxy() {
        ProxyFactory factory = new ProxyFactory(new ProxyTestServiceImpl());
        factory.addAdvice((MethodBeforeAdvice) (method, args1, target) ->
                System.out.println("你被拦截了:方法名为:" + method.getName() + " 参数为--" + Arrays.asList(args1)));
        factory.getProxy();
 }