手写 Spring Aop篇

上面三篇文档介绍了bean的生命周期。通知是如何绑定的,代理对象是如何产生的以及aop是如何调用的呢。

一个aop切面包含了哪些内容了

一个切面有多个切入点,每个切入点有不同的通知,通知分为before after around(此环境)

around 的通知有两个也是之前和之后,这个之前会在before之前执行,这个之后会在after之前执行。

那么aop是如何调用的呢。比如我们需要增强A类的query方法。如果A是一个接口,代理对象通过jdk动态代理生成,如果是一个类,代理对象通过cglib生成。那么增强的A类的query方法会有通知,切点会切query方法的通知。当调用query方法的时候,绑定的通知对象即该切面对象会调用增强的通知,不是代理对象。代理对象再调用query方法,调用完后,且秒对象会再调用around 之后的方法 和 after 方法。

比如 我们现在声明了一个切面(本应用只支持简单的表达式如execution(public * com.xx.service.OrderService.*(..)) 粒度只有类级别的)

此处并未按照Aspect api源码进行解析匹配对象

@XxComponent
@XxAspect
public class ServiceAop {

    @XxPointcut("execution(public * com.xx.service.OrderService.*(..))")
    public void pointCut01(){}

    @XxBefore("pointCut01()")
    public void beforeCut01() {
        System.out.println("==before 01==");
    }
    @XxAfter("pointCut01()")
    public void afterCut01() {
        System.out.println("==after 01==");
    }
    @XxAround("pointCut01()")
    public void aroundCut01(){
        System.out.println("==around 01==");
    }

}

切面对象 ServiceAop 切点OrderService的所有方法,切点通知pointCut01() 有XxBefore,XxAfter,XxAround三种通知

OrderService 有个query 方法需要增强 最终是 OrderService的代理对象执行query,ServiceAop 去执行三个切点的方法。所以我们是要将 OrderService 和 ServiceAop ,ServiceAop的切点,切点的通知进行绑定

XxAspectJ --> List<XxAspectPointCut>

XxAspectPointCut -->List<XxAspectAdvice>

具体的关系可以看gitee源码里面的:advisor 包对象关系

https://gitee.com/wanganfen/xx-spring/tree/master/simple-spring/src/main/java/com/xx/advisor

通知处理器:handle包 有之前、之后,环绕的处理器

https://gitee.com/wanganfen/xx-spring/tree/master/simple-spring/src/main/java/com/xx/handle

具体的执行就在创建代理类的invoke方法里面

    public Object invokeProxy(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object invoke = null;
        XxAspectJ xxAspectJ = new XxAspectJ(beanFactory);
        xxAspectJ = xxAspectJ.getXxAspectJByInstanceName(beanName);
        XxAspectPointCut xxAspectPointCut = xxAspectJ.getPointCuts().stream().filter(x -> x.getInstanceMaps().keySet().contains(beanName)).findFirst().get();
        List<MethodAdviceHandle> beansOfType = (List<MethodAdviceHandle>) beanFactory.getBeansOfType().get(MethodAdviceHandle.class);
        List<MethodAdviceHandle> methodAdviceHandleList = beansOfType.stream().sorted(Comparator.comparing(MethodAdviceHandle::order)).collect(Collectors.toList());
        List<XxAspectAdvice> advices = xxAspectPointCut.getAdvices();

        for (MethodAdviceHandle methodAdviceHandle : methodAdviceHandleList) {
            methodAdviceHandle.applyMethodBeforeAdviceHandleInitialization(xxAspectJ.getTarget(),advices,args);

        }
        if(Objects.isNull(proxy)){
            invoke = method.invoke(target, args);
        }else{
            invoke = methodProxy.invokeSuper(proxy, args);
        }

        for (MethodAdviceHandle methodAdviceHandle : methodAdviceHandleList) {
            methodAdviceHandle.applyMethodAfterAdviceHandleInitialization(xxAspectJ.getTarget(),advices,args);
        }
        return invoke;
    }

jdk动态代理传进去的是一个目标对象,即原始对象。

cglib动态代理传进去的是一个代理对象。

代理及逻辑:proxy

https://gitee.com/wanganfen/xx-spring/tree/master/simple-spring/src/main/java/com/xx/proxy

生成代理对象再Spring Bean的生命周期的最后一步

public class XxAutoProxyCreatorBeanPostProcessor implements XxBeanPostProcessor{

    private final XxDefaultListableBeanFactory beanFactory;

    public XxAutoProxyCreatorBeanPostProcessor(XxDefaultListableBeanFactory beanFactory){
        this.beanFactory = beanFactory;
    }

    @Override
    public Object applyObjectBeforeInstance(String beanName, Object instance) {
        List<XxAspectJ> xxAspectJList = new ArrayList<>(beanFactory.getXxAspectJMaps().values());
        xxAspectJList.forEach(x->{
            List<XxAspectPointCut> pointCuts = x.getPointCuts();
            pointCuts.forEach(y->{
                if(y.getInstanceMaps().keySet().contains(beanName)){
                    XxBeanDefinition xxBeanDefinition = beanFactory.getXxBeanDefinitionMaps().get(beanName);
                    xxBeanDefinition.setProxy(true);
                }
            });
        });
        return instance;
    }

    @Override
    public Object applyObjectAfterInstance(String beanName, Object instance) {
        XxBeanDefinition xxBeanDefinition = beanFactory.getXxBeanDefinitionMaps().get(beanName);
        if(xxBeanDefinition.isProxy){
            return getProxy(beanName,instance);
        }
        return instance;
    }

    private Object getProxy(String beanName , Object instance){
        ProxyFactory proxyFactory = new ProxyFactory(beanName,instance,beanFactory);
        return proxyFactory.createProxy();
    }
}

通常我们写的jdk或者是cglib动态代理的案例,目标对象都是写死了。但是有ioc之后,在这个对象的生命周期中就可以动态的去生成代理对象了,并且直接调用好已经绑定的通知了。

手写详情可见地址

https://gitee.com/wanganfen/xx-spring/tree/master/simple-spring

主要包:aop 包 和 proxy包

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值