AOP实现方式
AOP底层实现原理主要有三种:
- 代理:在运行时生成代理类字节码。
- JDK动态代理,只能针对接口代理。
- cglib,可以针对类和接口。
- ajc编译器增强:编译器在编译class类文件时,把通知的代码织入到目标类的字节码中。
- agent类加载:agent在加载目标类时,修改目标类的字节码,织入增强功能。
proxy
JDK动态代理
cglib
ajc编译器
1. 创建目标类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Service public class MyService {
private static final Logger log = LoggerFactory.getLogger(MyService.class);
public void test(){ log.info("test()"); test2(); }
public void test2(){ log.info("test2()"); } }
|
2. 创建切面
1 2 3 4 5 6 7 8 9 10 11
| @Aspect
public class MyAspect {
private static final Logger log = LoggerFactory.getLogger(MyAspect.class);
@Before("execution(* com.spring.study.aop.service.MyService.*())") public void before(){ log.info("before()"); } }
|
3. maven增加编译插件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <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>warning</Xlint> <encoding>UTF-8</encoding> </configuration> </plugin>
|
4. 编译,IDEA编译路径:maven->plugins->aspectj:complie
5. 结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Service public class MyService { private static final Logger log = LoggerFactory.getLogger(MyService.class);
public MyService() { }
public void test() { MyAspect.aspectOf().before(); log.info("test()"); this.test2(); }
public void test2() { MyAspect.aspectOf().before(); log.info("test2()"); } }
|
参考资料如下:
aspectj-maven-plugin开源项目
aspectj-maven-plugin
agent类加载
增加VM参数:-javaagent:D:\Code\Tools\Maven\Repository\org\aspectj\aspectjweaver\1.9.5
在类加载时对目标类进行增强
JDK代理
JDK代理特点:
- JDK代理只能针对接口进行代理。
- JDK代理类和目标类是兄弟关系,实现共同的接口。代理类和目标类之间不可以转换。
- 目标类可以是fianl类型。
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
| public class JdkProxyTest {
interface Foo{ void foo(); void foo2(); }
static class FooImpl implements Foo{ @Override public void foo() { System.out.println("foo"); }
@Override public void foo2() { System.out.println("foo2"); } }
public static void main(String[] args) { ClassLoader loader = JdkProxyTest.class.getClassLoader(); FooImpl target = new FooImpl(); Foo proxy = (Foo) Proxy.newProxyInstance(loader, new Class[]{Foo.class}, (p, method, args1) -> { System.out.println("before invoke foo "); Object result = method.invoke(target,args1); System.out.println("after invoke foo "); return result; }); proxy.foo(); proxy.foo2(); } }
|
执行结果如下:
1 2 3 4 5 6 7
| //输出结果如下: before invoke foo foo after invoke foo before invoke foo foo2 after invoke foo
|
CGLIB代理
CGLIB代理特点:
- 代理类是子类,目标类是父类:意味着目标类不能是final。
- final方法也不能增强。
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
| public class CglibProxyTest {
static class Target { public void foo() { System.out.println("foo"); }
public final void foo2() { System.out.println("foo2"); } }
public static void main(String[] args) { Target target = new Target(); Target proxy = (Target) Enhancer.create(Target.class, (MethodInterceptor) (obj, method, args1, methodProxy) -> { System.out.println("before"); Object result = method.invoke(target, args1); System.out.println("after"); return result; }); proxy.foo(); proxy.foo2(); } }
|
执行结果如下:
Author:
Desperado
Permalink:
http://xstar.life/2024/08/22/javaProxy/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Slogan:
Do you believe in DESTINY?