AOP 实现之 ajc 编译器
使用非代理的形式实现AOP即使用了ajc的编辑器,改写了目标对象的class文件,和spring没有联系
实现的话需要增加ajc编译插件的pom依赖
使用的不广泛,但是可以对静态方法进行增强
-
编译器也能修改 class 实现增强
-
编译器增强能突破代理仅能通过方法重写增强的限制:可以对构造方法、静态方法等实现增强
注意
版本选择了 java 8, 因为目前的 aspectj-maven-plugin 1.14.0 最高只支持到 java 16
一定要用 maven 的 compile 来编译, idea 不会调用 ajc 编译器
插件依赖
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14.0</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>8</source>
<target>8</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
package com.butch.a09;
import com.butch.a09.service.MyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class A09 {
private static final Logger log = LoggerFactory.getLogger(A09.class);
public static void main(String[] args) {
// ConfigurableApplicationContext context = SpringApplication.run(A09.class, args);
// MyService service = context.getBean(MyService.class);
//
// log.debug("service class: {}", service.getClass());
// service.foo();
//
// context.close();
new MyService().foo();
/*
学到了什么
1. aop 的原理并非代理一种, 编译器也能玩出花样
*/
}
}
package com.butch.a09.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 static void foo() {
log.debug("foo()");
}
}
package com.butch.a09.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Aspect // ⬅️注意此切面并未被 Spring 管理
public class MyAspect {
private static final Logger log = LoggerFactory.getLogger(MyAspect.class);
@Before("execution(* com.butch.a09.service.MyService.foo())")
public void before() {
log.debug("before()");
}
}
AOP 实现之 agent 类加载
-
版本选择了 java 8, 因为目前的 aspectj-maven-plugin 1.14.0 最高只支持到 java 16
-
运行时需要在 VM options 里加入 -javaagent:C:/Users/manyh/.m2/repository/org/aspectj/aspectjweaver/1.9.7/aspectjweaver-1.9.7.jar 把其中 C:/Users/manyh/.m2/repository 改为你自己 maven 仓库起始地址
package com.butch.a10;
import com.butch.a10.service.MyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@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);
log.debug("service class: {}", service.getClass());
service.foo();
context.close();
/*
学到了什么
1. aop 的原理并非代理一种, agent 也能, 只要字节码变了, 行为就变了
*/
}
}
package com.butch.a10.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Aspect // ⬅️注意此切面并未被 Spring 管理
public class MyAspect {
private static final Logger log = LoggerFactory.getLogger(MyAspect.class);
@Before("execution(* com.butch.a10.service.MyService.*")
public void before() {
log.debug("before()");
}
}
package com.butch.a10.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 void foo() {
log.debug("foo()");
this.bar();
}
public void bar() {
log.debug("bar()");
}
}