1. Spring动态代理的概念
      • 概念:通过代理类为原始类或目标类增加额外功能
      • 好处:利于原始类的维护
    2. 搭建开发环境

      1. <dependency>
      2. <groupId>org.springframework</groupId>
      3. <artifactId>spring-aop</artifactId>
      4. <version>5.1.4.RELEASE</version>
      5. </dependency>
      6. <dependency>
      7. <groupId>org.aspectj</groupId>
      8. <artifactId>aspectjrt</artifactId>
      9. <version>1.5.4</version>
      10. <scope>runtime</scope>
      11. </dependency>
      12. <dependency>
      13. <groupId>org.aspectj</groupId>
      14. <artifactId>aspectjweaver</artifactId>
      15. <version>1.8.7</version>
      16. <scope>runtime</scope>
      17. </dependency>
    3. Spring动态代理的开发步骤

      • 创建原始对象(目标对象)

        1. public class UserServiceImpl implements UserService{
        2. @Override
        3. public void register(User user) {
        4. System.out.println("UserServiceImpl.register 业务运算+DAO");
        5. }
        6. @Override
        7. public boolean login(String name, String password) {
        8. System.out.println("UserServiceImpl.login");
        9. return true;
        10. }
        11. }
      • 额外功能

        • MethodBeforeAdvice接口
          • 额外的功能书写在接口的实现类中,运行在原始方法执行之前执行
            1. public class Before implements MethodBeforeAdvice {
            2. /*
            3. * 需要把运行在原始方法之前执行的额外功能书写在before方法中
            4. * */
            5. @Override
            6. public void before(Method method, Object[] args, Object target) throws Throwable {
            7. System.out.println("Before.before");
            8. }
            9. }
      • 定义切入点

        • 切入点:额外功能加入的位置
        • 目的:由程序员根据需要,决定额外功能加入到哪个原始方法
        • 简单的测试:所有方法都作为切入点,都加入原始功能
          • 配置文件增加内容如下:
            1. <aop:config>
            2. <!--效果:所有方法都作为切入点-->
            3. <aop:pointcut id="pc" expression="execution(* *(..))"/>
            4. </aop:config>
    4. 组装(2、3整合)

      • 配置文件如下
        1. <aop:config>
        2. <!--效果:所有方法都作为切入点-->
        3. <aop:pointcut id="pc" expression="execution(* *(..))"/> //两个*之间有一个空格,固定格式,不可更改
        4. <!--组装:把额外功能与切入点整合-->
        5. <aop:advisor advice-ref="before" pointcut-ref="pc"/>
        6. </aop:config>
    5. 调用

      • 目的:获得Spring工厂创建的动态代理对象,并进行调用

    ApplicationContext ctx=new ClassPathXMLApplicationContext(“applicationContxt.xml”);
    注意:1. Spring工厂通过原始对象的id获得的对象是代理对象(规定如此)
    2. 获得代理对象后,可以通过声明接口类型,存储代理对象
    UserService UserService=ctx.getBean(“userService”);

    1. Spring动态代理细节分析
      • Spring创建的动态代理类在哪?
        • Spring框架在运行时,通过动态字节码技术,在JVM中创建,运行在JVM内部,等程序运行结束,和JVM一起消失
        • 动态字节码技术:通过第三方动态字节码框架,在JVM中创建对应类的字节码,进而创建对象,当虚拟机结束,动态字节码跟着消失(如图所示)
        • 结论:动态代理不需要定义类文件,都是JVM在运行过程中动态创建的,所以不会造成静态代理时类文件数量过多影响项目管理的问题

    image.png

    • 动态代理编程会简化代理开发
      • 在额外功能不改变的前提下,创建其他目标类(原始类)的代理对象时,只需指定原始对象(目标即可)
    • 动态代理额外功能的维护性大大增强