【Spring】Spring AOP底层原理前置知识:代理模式中的静态代理

目录

1、Spring AOP底层原理概念

2、静态代理

2.1、介绍静态代理

2.2、静态代理示例

1、Spring AOP底层原理概念

        AOP是一种编程范式,用于在不修改原始代码的情况下向现有应用程序添加新功能。这种编程方式将应用程序分成许多独立的部分,称为切面。这些切面可以在应用程序的不同位置进行编写和维护,从而提高了应用程序的可重用性和可维护性。

        AOP主要用于实现横切关注点(Cross-Cutting Concerns),例如日志记录、性能监测、事务管理等。通过AOP,我们可以将这些关注点与应用程序的其他部分分离开来,从而使应用程序更加模块化和易于维护。

        Spring AOP的底层原理:一开始Spring会创建IOC容器,然后会把所有的Bean进行创建和进行依赖注入,就是spring(new 类名())。当实现了AOP的话,spring会根据当前的bean动态的创建代理对象,就比如我当前有一个UserService类,这个类实现了AOP,然后spring为UserService类动态创建代理对象并且把这个代理对象配置成bean替换掉UserService类的bean,所以这时候从IOC容器中去拿到的UserService类的bean实际上是Spring为UserService类动态创建的代理对象的bean,如下:

@SpringBootTest(classes = AdviceTest.class)
@ComponentScan
@EnableAspectJAutoProxy
public class AdviceTest {
    @Test
    void contextLoads(@Autowired UserService userService) {
        System.out.println(userService.getClass());
        userService.add();
    }
}

运行结果:

动态代理是一项比较复杂的技术,要使用代理有几种方式,这里先从下面的代理模式中的静态代理说起

2、静态代理

2.1、介绍静态代理

静态代理是一种代理模式,代理模式是一种比较好的理解的设计模式。

简单来说就是:

(1)我们使用代理对象来增强目标对象(target obiect),这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。

(2)将核心业务代码和非核心的公共代码分离解耦,提高代码可维护性,让被代理类专注业务降低代码复杂度。被代理类专注业务、代理类非核心的公共代码,通常用代理实现比如拦截器,事务控制,还有测试框架 mock、用户鉴权、日志、全局异常处理等功能

总的来说,代理模式的主要作用是扩展目标对象的功能,比如说在目标对象的某个方法执行前后你可以增加一些自定义的操作。

举个例子:客户找老板, 让秘书登记来访人员和时间, 记录来访用时,并且让秘书拒绝老板不想见的客户。 秘书充当代理角色

        当客户要找老板办事情的时候,如果客户是直接去找老板,就可能会耽误老板的许多事情,就比如是一些推销的等不重要的客户就会耽误老板的许多时间,这时候就可以在中间加一个增强——秘书,一些不重要的客户或者重要的客户先到秘书这里进行登记然后由秘书决定这个客户去不去见老板,这就相当于代码当中的用户鉴权,说白了就是有没有一个权限去访问对应的接口。还有就是秘书要记录每一个来访客户,这就相当于代码中的记录日志,此时这个秘书就是充当了代理类。老板就是目标对象(被代理类)。生活当中还有许多这种代理模式的例子

2.2、静态代理示例

使用代码实现上面的例子:

//CEO相当于上面例子中的老板
public class CEO {
    public void meeting(String name){
        System.out.println("接见客户:" + name);
    }
}


//CEOProxy相当于上面例子中的秘书
public class CEOProxy extends CEO{
    @Override
    public void meeting(String name) {
        //CEOProxy就相当于代理类,代理类是继承了被代理类CEO的,
        //可以在代理类中为被代理类中的方法进行增强而不用需改被代理类中的代码
        //相当于记录日志,增强方法
        System.out.println("记录来访人员:" + name);
        //相当于权限控制,增强方法
        if ("张三".equals(name)) {
            super.meeting(name);
        }
    }
}


//测试类
public class StaticTest {
    @Test
    public void test(){
        //这里的CEO ceo = new CEOProxy();就相当于spring创建代理对象,
        //只不过这里的是静态代理,而spring的是动态代理
        //静态代理对象需要程序员自己创建,而动态代理对象是由程序运行时动态生成出来的字节码类
        CEO ceo = new CEOProxy();
        ceo.meeting("李四");
    }
}

在测试类中,当meeting方法中传递的参数为“李四”时,是不会调用到CEO中的meeting方法的,也就是当李四来访时,是见不到老板的

在测试类中,当meeting方法中传递的参数为“张三”时,会调用到CEO中的meeting方法,也就是当张三来访时,是见的到老板的

静态代理有的弊端:

  1. 编译期限制: 静态代理在编译期间生成代理类,因此在程序运行时无法动态修改代理类的行为。这意味着,如果需要在运行时动态地添加、删除或修改切面,就无法使用静态代理来实现。
  2. 维护成本高: 每次新增一个切面或者修改现有的切面,都需要重新生成代理类并重新编译整个程序。这样会增加维护的成本,尤其是在大型项目中。
  3. 类爆炸问题: 静态代理需要为每个被代理的类生成一个代理类,如果系统中存在大量的类需要被代理,就会导致类的数量激增,产生类爆炸问题,增加了项目的复杂性和内存消耗。
  4. 无法代理非接口类: 静态代理只能代理接口,无法直接代理普通类,因为代理类必须实现被代理类的接口。这在某些场景下会限制代理的使用范围。
  5. 无法处理运行时异常: 静态代理在编译期间确定了被代理类的方法,因此无法动态地处理被代理方法抛出的运行时异常。

推荐:

【Spring】AOP中的核心概念:通知(Advice)和切点(Pointcut)_aop的通知和切入点-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/138890487?spm=1001.2014.3001.5501

【Spring】初识 Spring AOP(面向切面编程)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/138724937?spm=1001.2014.3001.5501
【Spring】IOC/DI中常用的注解@Lazy、@Scope与@Conditional-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/138277932?spm=1001.2014.3001.5501

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值