@Aspect // ⬅️注意此切面并未被 Spring 管理
public class MyAspect {
private static final Logger log = LoggerFactory.getLogger(MyAspect.class);
@Before("execution(* com.itheima.service.MyService.*())")
public void before() {
log.debug("before()");
}
}
@Service
public class MyService {
private static final Logger log = LoggerFactory.getLogger(MyService.class);
public void foo() {
log.debug("foo()");
//this.bar();
}
}
@SpringBootApplication
public class A10 {
private static final Logger log = LoggerFactory.getLogger(A10.class);
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(A10.class, args);
MyService service = context.getBean(MyService.class);
// ⬇️MyService 并非代理, 但 foo 方法也被增强了, 做增强的 java agent, 在加载类时, 修改了 class 字节码
log.debug("service class: {}", service.getClass());
service.foo();
context.close();
/*
学到了什么
1. aop 的原理并非代理一种, agent 也能, 只要字节码变了, 行为就变了
*/
}
}
可见实现了前置通知并且MyService不是代理类。
MyAspect未加@Component注解所以未被Spring管理,所以注释掉Spring相关代码直接new一个类也能前置通知见下图
这说明AOP除了代理实现也能由ajc 编译器,代理通过方法重写实现,如果静态方法就无能为力,而ajc就可以,他能直接改.class文件。