手写高仿真Spring框架-AOP部分

7 篇文章 0 订阅

手写高仿真Spring框架

流行词:顶层设计 AOP 仿真

参考代码:https://gitee.com/li-lixiang/lean-spring-2.0.git

在前面的blog中,已经实现Spring IOC、DI、MVC,并调试代码展示前后交互结果。接下来学习Spring核心AOP,高仿手写AOP实现逻辑。

顶层设计

实现日志监控

用代理类进行解耦,AopProxy接口,有jdk实现方式与cglib实现方式

JDK实现AopProxy


定义AopProxy,用invoke方法增强原有方法,按照拦截器链去执行增强方法invoke。

 

AOP具体实现

在原有依赖注入的时候,需要增加AOP的情况,优化原有ApplicationContext->refresh->doAutowired->getBean->stantiateBean方法。当需要实例化的类符合切面表达式时,则进行切入(将用proxy增强后的实例代替)。

    private Object instantiateBean(String beanName, GPBeanDefinition gpBeanDefinition) {
        //1、拿到要实例化的对象的类名
        String className = gpBeanDefinition.getBeanClassName();

        //2、反射实例化,得到一个对象
        Object instance = null;
        try {
//            gpBeanDefinition.getFactoryBeanName()
            //假设默认就是单例,细节暂且不考虑,先把主线拉通
            if(this.factoryBeanObjectCache.containsKey(className)){
                instance = this.factoryBeanObjectCache.get(className);
            }else {
                Class<?> clazz = Class.forName(className);
                instance = clazz.newInstance();

                //当需要实例化的类符合切面表达式时,则进行切入(将用proxy增强后的实例代替)
                GPAdvisedSupport config = instantionAopConfig(gpBeanDefinition);
                config.setTargetClass(clazz);
                config.setTarget(instance);
                //符合PointCut的规则的话,创建代理对象
                if(config.pointCutMatch()) {
                    instance = createProxy(config).getProxy();
                }

                this.factoryBeanObjectCache.put(className,instance);
                this.factoryBeanObjectCache.put(gpBeanDefinition.getFactoryBeanName(),instance);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        return instance;
    }

 

 

初始化配置

instantionAopConfig

设置方法执行器链

在AdviceSupport->setTargetClass->parse方法中封装方法的拦截器链

 

作业:完成around切面方法拦截器

在切面中增加around方法,在service执行前和执行后执行around方法

实现步骤:

  1. 在application.properties中增加配置如下
    #环绕执行
    aspectAround=around
  2. 在GPAppConfig中增加aspectAround属性
        private String aspectAround;

     

  3. 在GPAdvisedSupport中,增加拦截器链对around方法的切入
    //around
                        if(!(null == config.getAspectAround() || "".equals(config.getAspectAround()))) {
                            //创建一个Advivce
                            advices.add(new GPMethodAroundAdviceInterceptor(aspectMethods.get(config.getAspectAround()),aspectClass.newInstance()));
                        }
  4. 创建类GPMethodAroundAdviceInterceptor 
    /**
     * Copyright (C), 2015-2020, XXX有限公司
     * FileName: GPMethodAroundAdviceInterceptor
     * Author:   lilx
     * Date:     2020/12/5 14:46
     * Description: 环绕执行
     * History:
     * <author>          <time>          <version>          <desc>
     * 作者姓名           修改时间           版本号              描述
     */
    package com.gupaoedu.vip.spring.formework.aop.aspect;
    
    import com.gupaoedu.vip.spring.formework.aop.intercept.GPMethodInterceptor;
    import com.gupaoedu.vip.spring.formework.aop.intercept.GPMethodInvocation;
    
    import java.lang.reflect.Method;
    
    /**
     * 〈一句话功能简述〉<br> 
     * 〈环绕执行〉
     *
     * @author lilx
     * @create 2020/12/5
     * @since 1.0.0
     */
    public class GPMethodAroundAdviceInterceptor extends GPAbstractAspectAdvice implements GPAdvice, GPMethodInterceptor {
        private GPJoinPoint joinPoint;
    
        public GPMethodAroundAdviceInterceptor(Method aspectMethod, Object aspectTarget) {
            super(aspectMethod, aspectTarget);
        }
        public void around(int i){
            if(i==0){
                System.out.println("GPMethodAroundAdviceInterceptor.around(...) start");
            }else{
                System.out.println("GPMethodAroundAdviceInterceptor.around(...) end");
            }
        }
    
        @Override
        public Object invoke(GPMethodInvocation mi) throws Throwable {
            //从被织入的代码中才能拿到,JoinPoint
            this.joinPoint = mi;
            around(0);
            Object retVal = mi.proceed();
            around(1);
            return retVal;
        }
    
    }

     

  5. 完成

 

运行结果:

把其他切面方法注释掉,如下日志

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值