AOP实现之agent类加载
AOP的另一种实现及原理
A11Application.java
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();
}
}
MyService.java
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()");
}
}
MyAspect.java
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()");
}
}
MyService.class反编译后的代码
java
//
// 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()");
}
}