Spring源码-SpringAop执行过程详解


前言

暂无

一、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代理类创建过程

在这里插入图片描述

四、springAop代理类执行过程

在这里插入图片描述

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

在这里插入图片描述

六、自己实现一个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();
 }

总结

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值