• Spring底层原理学习笔记--第十讲--(aop之agent增强)


    AOP实现之agent类加载

    AOP的另一种实现及原理

    A11Application.java

    package com.lucifer.itheima.a11;
    
    import com.lucifer.itheima.a11.service.MyService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    /**
     *  注意几点
     *  1.版本选择了java 8,因为目前的aspectj-maven-plugin 1.40.0 最高只支持到java 16
     *  2.运行时需要在VM option里加入 -jaavaagent:C:/Users/manyh/.m2/repository/org/aspectj/aspectjweaver/1.9.7.jar
     *      把其中C:/Users/manyh/.m2/repository改为自己maven仓库起始地址
     *
     *  在类加载阶段修改了MyService类的字节码
     *
     *  目前为止,讲了三种aop的实现,第一种就是代理实现,第二种就是上讲学到的用aspect编译器,在编译阶段修改字节码,这节课讲的是agent,agent就是在java类加载阶段去改动我们待增强的字节码
     *  但是后面这两种没有流行起来,实际开发过程中开始以代理为主
     */
    @SpringBootApplication
    @Slf4j
    public class A11Application {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(A11Application.class,args);
            MyService service = context.getBean(MyService.class);
    
    
            //MyService 并非代理,但foo方法也被增强了,做增强的java agent,在加载类时,修改了class字节码
            log.info("service class:{}",service.getClass());
    
            //输出结果为
            //before()
    //        2023-11-14 10:51:15.898  INFO 18864 --- [           main] c.lucifer.itheima.a11.service.MyService  : foo()
            //before()
    //        2023-11-14 10:51:15.898  INFO 18864 --- [           main] c.lucifer.itheima.a11.service.MyService  : bar()
            service.foo();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    MyService.java

    package com.lucifer.itheima.a11.service;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Service;
    
    @Service
    @Slf4j
    public class MyService {
    
        final public void foo(){
            log.info("foo()");
            bar();
        }
    
        public void bar(){
            log.info("bar()");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    MyAspect.java

    package com.lucifer.itheima.a11.aop;
    
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    @Aspect     //注意此切面未被Spring管理
    @Slf4j
    public class MyAspect {
    
        @Before("execution(* com.lucifer.itheima.a11.service.MyService.*())")
        public void before(){
            log.info("before()");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    MyService.class反编译后的代码

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package com.lucifer.itheima.a11.service;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Service;
    
    @Service
    public class MyService {
        private static final Logger log = LoggerFactory.getLogger(MyService.class);
    
        public MyService() {
        }
    
        public final void foo() {
        	MyAspect.aspectOf().before();
            log.info("foo()");
            this.bar();
        }
    
        public void bar() {
        	MyAspect.aspectOf().before();
            log.info("bar()");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  • 相关阅读:
    在Ubuntu/Linux中自动备份MySQL数据库
    JVM理解(二)
    Code Inspector:点击页面元素自动定位到代码
    Python运行过程简单介绍
    【函数式编程】Optional接口
    pytorch中torch.where()使用方法
    UE基础 —— 工具和编辑器
    windows使用mysqldump
    Java的基础语法(三)
    牛客题目——链表的奇偶重排、输出二叉树的右视图、括号生成、字符流中第一个不重复的字符
  • 原文地址:https://blog.csdn.net/weixin_42594143/article/details/134395255