代码参考项目 demo6_advanced_aspectj_01
收获💡
编译器也能修改 class 实现增强
编译器增强能突破代理仅能通过方法重写增强的限制:可以对构造方法、静态方法等实现增强
项目地址:demo6_advanced_aspectj_01
https://github.com/LJay997/demo6_advanced_aspectj_01
查看IDEA 编译的class文件可看出ajc帮我们修改了源码实现了增强静态方法

代码参考项目 demo6_advanced_aspectj_02
收获💡
类加载时可以通过 agent 修改 class 实现增强
demo6_advanced_aspectj_02
https://github.com/LJay997/demo6_advanced_aspectj_02项目地址:git@github.com:LJay997/demo6_advanced_aspectj_02.git
Arthas
https://github.com/alibaba/arthas/blob/master/README_CN.md 反编译运行时的文件 下载arthas-boot.jar,然后用java -jar的方式启动:
- curl -O https://arthas.aliyun.com/arthas-boot.jar
- java -jar arthas-boot.jar
运行 A10,选择3

运行成功后 使用命令 jad (Decompile class 使用 help命令可查看帮助)
jad jad com.itheima.service.MyService

查看运行时编译文件。可见 aop foo()foo()内部又调用了自己的 bar()也可以被增强的。
Spring Aop失效的情況及解决办法
http://t.csdn.cn/aRC6D
- interface Foo {
- void foo();
- int bar();
- }
- class Target implements Foo {
-
- @Override
- public int bar() {
- return 0;
- }
-
- @Override
- public void foo() {
- System.out.println("target foo");
- }
- }
- public class JdkProxy {
-
- public static void main(String[] args) throws IOException {
- // method.invoke 需要传递 target
- Target target = new Target();
- ClassLoader loader = JdkProxy.class.getClassLoader();
- // Proxy.newProxyInstance ClassLoader [] Class>[]
- // java.lang.reflect 生成的代理对象需要是接口实现的方法 代理与目标是同级关系
- Foo proxy = (Foo) Proxy.newProxyInstance(loader, new Class[]{Foo.class}, (tmpProxy, method, args1) -> {
- System.out.println("before");
- // method.invoke 参数1 需要传递
- return method.invoke(target, args1);
- });
- // 执行代理方法
- proxy.foo();
- // 获取当前代理方法的类
- System.out.println(proxy.getClass());
- // 防止程序自己终止
- System.in.read();
- }
- }
使用arthas工具查看 JdkProxy运行期间动态生成(ASM)生成的代理类的源码。
- # 运行 arthas
- java -jar .\arthas-boot.jar
-
- # 查看到程序的代号输入(回车确认)
- 4
-
- # jad 命令反编译
- jad $Proxy0

- package a11;
-
- import a11.Foo;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import java.lang.reflect.UndeclaredThrowableException;
-
- final class $Proxy0
- extends Proxy
- implements Foo {
- // 获取接口所有的方法
- private static Method m1;
- private static Method m2;
- private static Method m3;
- private static Method m4;
- private static Method m0;
-
- // 实现构造方法 Proxy
- public $Proxy0(InvocationHandler invocationHandler) {
- super(invocationHandler);
- }
-
- public final boolean equals(Object object) {
- try {
- return (Boolean)this.h.invoke(this, m1, new Object[]{object});
- }
- catch (Error | RuntimeException throwable) {
- throw throwable;
- }
- catch (Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
-
- public final String toString() {
- try {
- return (String)this.h.invoke(this, m2, null);
- }
- catch (Error | RuntimeException throwable) {
- throw throwable;
- }
- catch (Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
-
- public final int bar() {
- try {
- return (Integer)this.h.invoke(this, m3, null);
- }
- catch (Error | RuntimeException throwable) {
- throw throwable;
- }
- catch (Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
-
- public final void foo() {
- try {
- this.h.invoke(this, m4, null);
- return;
- }
- catch (Error | RuntimeException throwable) {
- throw throwable;
- }
- catch (Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
-
- public final int hashCode() {
- try {
- return (Integer)this.h.invoke(this, m0, null);
- }
- catch (Error | RuntimeException throwable) {
- throw throwable;
- }
- catch (Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
-
- static {
- try {
- m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
- m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
- m3 = Class.forName("a11.Foo").getMethod("bar", new Class[0]);
- m4 = Class.forName("a11.Foo").getMethod("foo", new Class[0]);
- m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
- return;
- }
- catch (NoSuchMethodException noSuchMethodException) {
- throw new NoSuchMethodError(noSuchMethodException.getMessage());
- }
- catch (ClassNotFoundException classNotFoundException) {
- throw new NoClassDefFoundError(classNotFoundException.getMessage());
- }
- }
- }


main 方法中补充
-
- byte[] dump = $Proxy0Dump.dump();
-
- ClassLoader classLoader = new ClassLoader() {
- @Override
- protected Class> findClass(String name) throws ClassNotFoundException {
- // 将字节数组转换为Class 类的实例
- return super.defineClass(name, dump, 0, dump.length);
- }
- };
-
- Class> proxy0 = classLoader.loadClass("$Proxy0");
- Constructor> constructor = proxy0.getConstructor(InvocationHandler.class);
- Foo proxy = (Foo)constructor.newInstance(new InvocationHandler() {
- @Override
- public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
- return null;
- }
- });
-
- proxy.foo();
-
- // .....JDK 代理方法
- Target target = new Target();
- // ......
在反射调用第17次时候 代理类变化了
16:jdk.internal.reflect.NativeMethodAccessorImpl@cb5822 ->
17:jdk.internal.reflect.GeneratedMethodAccessor2@26653222
- public class TestMethodInvoke {
- public static void main(String[] args) throws Exception {
- Method foo = TestMethodInvoke.class.getMethod("foo", int.class);
- for (int i = 1; i <= 17; i++) {
- show(i, foo);
- foo.invoke(null, i);
- }
- System.in.read();
- }
-
- // 方法反射调用时, 底层 MethodAccessor 的实现类
- private static void show(int i, Method foo) throws Exception {
- Method getMethodAccessor = Method.class.getDeclaredMethod("getMethodAccessor");
- getMethodAccessor.setAccessible(true);
- Object invoke = getMethodAccessor.invoke(foo);
- if (invoke == null) {
- System.out.println(i + ":" + null);
- return;
- }
- Field delegate = Class.forName("jdk.internal.reflect.DelegatingMethodAccessorImpl").getDeclaredField("delegate");
- delegate.setAccessible(true);
- System.out.println(i + ":" + delegate.get(invoke));
- }
-
- public static void foo(int i) {
- System.out.println(i + ":" + "foo");
- }
- }
jdk 动态代理要求目标必须实现接口,生成的代理类实现相同接口,因此代理与目标之间是平级兄弟关系
- import org.springframework.cglib.proxy.MethodInterceptor;
- import org.springframework.cglib.proxy.MethodProxy;
-
- import java.io.IOException;
- import java.lang.reflect.Method;
-
- public class CglibProxy {
- static class Target {
- void foo() {
- System.out.println("target foo");
- }
- }
-
- public static void main(String[] args) throws IOException {
- Target target = new Target();
-
- // public static Object create(Class type, Callback callback) 第二个参数 使用 MethodInterceptor extends Callback
- // cglib 生产的类型为目标类型的 子类型(方法重写) 目标方法&目标类不能是final类型的
- Target proxy = (Target)Enhancer.create(Target.class, new MethodInterceptor() {
- @Override
- public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
- System.out.println("before");
- // Object invoke = method.invoke(target, objects); // 用方法反射调用目标
- Object invoke = methodProxy.invoke(target, objects); // 没有用反射 - 推荐
- // Object invoke = methodProxy.invokeSuper(o, objects); // 没有用反射 需要代理
- System.out.println("after");
- return invoke;
- }
- });
-
- proxy.foo();
- System.out.println(proxy.getClass());
- System.in.read();
- }
- }
arthas 获取运行时class
- package a11;
-
- import a11.CglibProxy;
- import java.lang.reflect.Method;
- import org.springframework.cglib.core.ReflectUtils;
- import org.springframework.cglib.core.Signature;
- import org.springframework.cglib.proxy.Callback;
- import org.springframework.cglib.proxy.Factory;
- import org.springframework.cglib.proxy.MethodInterceptor;
- import org.springframework.cglib.proxy.MethodProxy;
-
- public class CglibProxy$Target$$EnhancerByCGLIB$$f6222c24
- extends CglibProxy.Target
- implements Factory {
- // Method MethodProxy 重点
- private boolean CGLIB$BOUND;
- public static Object CGLIB$FACTORY_DATA;
- private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
- private static final Callback[] CGLIB$STATIC_CALLBACKS;
- private MethodInterceptor CGLIB$CALLBACK_0;
- private static Object CGLIB$CALLBACK_FILTER;
- private static final Method CGLIB$foo$0$Method;
- private static final MethodProxy CGLIB$foo$0$Proxy;
- private static final Object[] CGLIB$emptyArgs;
- private static final Method CGLIB$equals$1$Method;
- private static final MethodProxy CGLIB$equals$1$Proxy;
- private static final Method CGLIB$toString$2$Method;
- private static final MethodProxy CGLIB$toString$2$Proxy;
- private static final Method CGLIB$hashCode$3$Method;
- private static final MethodProxy CGLIB$hashCode$3$Proxy;
- private static final Method CGLIB$clone$4$Method;
- private static final MethodProxy CGLIB$clone$4$Proxy;
-
- static void CGLIB$STATICHOOK1() {
- CGLIB$THREAD_CALLBACKS = new ThreadLocal();
- CGLIB$emptyArgs = new Object[0];
- Class> clazz = Class.forName("a11.CglibProxy$Target$$EnhancerByCGLIB$$f6222c24");
- Class> clazz2 = Class.forName("java.lang.Object");
- Method[] methodArray = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, clazz2.getDeclaredMethods());
- CGLIB$equals$1$Method = methodArray[0];
- CGLIB$equals$1$Proxy = MethodProxy.create(clazz2, clazz, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
- CGLIB$toString$2$Method = methodArray[1];
- CGLIB$toString$2$Proxy = MethodProxy.create(clazz2, clazz, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
- CGLIB$hashCode$3$Method = methodArray[2];
- CGLIB$hashCode$3$Proxy = MethodProxy.create(clazz2, clazz, "()I", "hashCode", "CGLIB$hashCode$3");
- CGLIB$clone$4$Method = methodArray[3];
- CGLIB$clone$4$Proxy = MethodProxy.create(clazz2, clazz, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
- clazz2 = Class.forName("a11.CglibProxy$Target");
- CGLIB$foo$0$Method = ReflectUtils.findMethods(new String[]{"foo", "()V"}, clazz2.getDeclaredMethods())[0];
- CGLIB$foo$0$Proxy = MethodProxy.create(clazz2, clazz, "()V", "foo", "CGLIB$foo$0");
- }
- // 带原始功能的方法
- final void CGLIB$foo$0() {
- super.foo();
- }
- // 带增强功能的方法
- @Override
- final void foo() {
- MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
- if (methodInterceptor == null) {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BIND_CALLBACKS(this);
- methodInterceptor = this.CGLIB$CALLBACK_0;
- }
- if (methodInterceptor != null) {
- Object object = methodInterceptor.intercept(this, CGLIB$foo$0$Method, CGLIB$emptyArgs, CGLIB$foo$0$Proxy);
- return;
- }
- super.foo();
- }
-
- final boolean CGLIB$equals$1(Object object) {
- return super.equals(object);
- }
-
- public final boolean equals(Object object) {
- MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
- if (methodInterceptor == null) {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BIND_CALLBACKS(this);
- methodInterceptor = this.CGLIB$CALLBACK_0;
- }
- if (methodInterceptor != null) {
- Object object2 = methodInterceptor.intercept(this, CGLIB$equals$1$Method, new Object[]{object}, CGLIB$equals$1$Proxy);
- return object2 == null ? false : (Boolean)object2;
- }
- return super.equals(object);
- }
-
- final String CGLIB$toString$2() {
- return super.toString();
- }
-
- public final String toString() {
- MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
- if (methodInterceptor == null) {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BIND_CALLBACKS(this);
- methodInterceptor = this.CGLIB$CALLBACK_0;
- }
- if (methodInterceptor != null) {
- return (String)methodInterceptor.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy);
- }
- return super.toString();
- }
-
- final int CGLIB$hashCode$3() {
- return super.hashCode();
- }
-
- public final int hashCode() {
- MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
- if (methodInterceptor == null) {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BIND_CALLBACKS(this);
- methodInterceptor = this.CGLIB$CALLBACK_0;
- }
- if (methodInterceptor != null) {
- Object object = methodInterceptor.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
- return object == null ? 0 : ((Number)object).intValue();
- }
- return super.hashCode();
- }
-
- final Object CGLIB$clone$4() throws CloneNotSupportedException {
- return super.clone();
- }
-
- protected final Object clone() throws CloneNotSupportedException {
- MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
- if (methodInterceptor == null) {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BIND_CALLBACKS(this);
- methodInterceptor = this.CGLIB$CALLBACK_0;
- }
- if (methodInterceptor != null) {
- return methodInterceptor.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy);
- }
- return super.clone();
- }
-
- public static MethodProxy CGLIB$findMethodProxy(Signature signature) {
- String string = ((Object)signature).toString();
- switch (string.hashCode()) {
- case -1268936465: {
- if (!string.equals("foo()V")) break;
- return CGLIB$foo$0$Proxy;
- }
- case -508378822: {
- if (!string.equals("clone()Ljava/lang/Object;")) break;
- return CGLIB$clone$4$Proxy;
- }
- case 1826985398: {
- if (!string.equals("equals(Ljava/lang/Object;)Z")) break;
- return CGLIB$equals$1$Proxy;
- }
- case 1913648695: {
- if (!string.equals("toString()Ljava/lang/String;")) break;
- return CGLIB$toString$2$Proxy;
- }
- case 1984935277: {
- if (!string.equals("hashCode()I")) break;
- return CGLIB$hashCode$3$Proxy;
- }
- }
- return null;
- }
-
- public CglibProxy$Target$$EnhancerByCGLIB$$f6222c24() {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24 cglibProxy$Target$$EnhancerByCGLIB$$f6222c24 = this;
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BIND_CALLBACKS(cglibProxy$Target$$EnhancerByCGLIB$$f6222c24);
- }
-
- public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] callbackArray) {
- CGLIB$THREAD_CALLBACKS.set(callbackArray);
- }
-
- public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] callbackArray) {
- CGLIB$STATIC_CALLBACKS = callbackArray;
- }
-
- private static final void CGLIB$BIND_CALLBACKS(Object object) {
- block2: {
- Object object2;
- block3: {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24 cglibProxy$Target$$EnhancerByCGLIB$$f6222c24 = (CglibProxy$Target$$EnhancerByCGLIB$$f6222c24)object;
- if (cglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BOUND) break block2;
- cglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BOUND = true;
- object2 = CGLIB$THREAD_CALLBACKS.get();
- if (object2 != null) break block3;
- object2 = CGLIB$STATIC_CALLBACKS;
- if (CGLIB$STATIC_CALLBACKS == null) break block2;
- }
- cglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])object2)[0];
- }
- }
-
- @Override
- public Object newInstance(Callback[] callbackArray) {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24 cglibProxy$Target$$EnhancerByCGLIB$$f6222c24 = new CglibProxy$Target$$EnhancerByCGLIB$$f6222c24();
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$SET_THREAD_CALLBACKS(null);
- return cglibProxy$Target$$EnhancerByCGLIB$$f6222c24;
- }
-
- @Override
- public Object newInstance(Callback callback) {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$SET_THREAD_CALLBACKS(new Callback[]{callback});
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24 cglibProxy$Target$$EnhancerByCGLIB$$f6222c24 = new CglibProxy$Target$$EnhancerByCGLIB$$f6222c24();
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$SET_THREAD_CALLBACKS(null);
- return cglibProxy$Target$$EnhancerByCGLIB$$f6222c24;
- }
-
- @Override
- public Object newInstance(Class[] classArray, Object[] objectArray, Callback[] callbackArray) {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24 cglibProxy$Target$$EnhancerByCGLIB$$f6222c24;
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
- Class[] classArray2 = classArray;
- switch (classArray.length) {
- case 0: {
- cglibProxy$Target$$EnhancerByCGLIB$$f6222c24 = new CglibProxy$Target$$EnhancerByCGLIB$$f6222c24();
- break;
- }
- default: {
- throw new IllegalArgumentException("Constructor not found");
- }
- }
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$SET_THREAD_CALLBACKS(null);
- return cglibProxy$Target$$EnhancerByCGLIB$$f6222c24;
- }
-
- @Override
- public Callback getCallback(int n) {
- MethodInterceptor methodInterceptor;
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BIND_CALLBACKS(this);
- switch (n) {
- case 0: {
- methodInterceptor = this.CGLIB$CALLBACK_0;
- break;
- }
- default: {
- methodInterceptor = null;
- }
- }
- return methodInterceptor;
- }
-
- @Override
- public void setCallback(int n, Callback callback) {
- switch (n) {
- case 0: {
- this.CGLIB$CALLBACK_0 = (MethodInterceptor)callback;
- break;
- }
- }
- }
-
- @Override
- public Callback[] getCallbacks() {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$BIND_CALLBACKS(this);
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24 cglibProxy$Target$$EnhancerByCGLIB$$f6222c24 = this;
- return new Callback[]{this.CGLIB$CALLBACK_0};
- }
-
- @Override
- public void setCallbacks(Callback[] callbackArray) {
- Callback[] callbackArray2 = callbackArray;
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24 cglibProxy$Target$$EnhancerByCGLIB$$f6222c24 = this;
- this.CGLIB$CALLBACK_0 = (MethodInterceptor)callbackArray[0];
- }
-
- static {
- CglibProxy$Target$$EnhancerByCGLIB$$f6222c24.CGLIB$STATICHOOK1();
- }
- }
Spring 中对切点、通知、切面的抽象如下


切点:接口 Pointcut,典型实现 AspectJExpressionPointcut(在哪些地方增强)
通知:Advice 该接口仅仅作为标记使用 没做实质性的方法 典型使用的接口为 MethodInterceptor 所有通知会被统一转换为环绕通知 适配器模式的体现



MethodInterceptor 中可以间接的获取到 Joinpoint 的方法
切面:Advisor,包含一个 Advice 通知,PointcutAdvisor 包含一个 Advice 通知和一个 Pointcut(哪个人 在哪个地方Pointcut 做什么事情Advice)

代理相关类图(代理工厂需要 目标类(Target) + 哪个人(Advisor)即可完成 代理者的创建(Proxy) )
AopProxyFactory 根据 proxyTargetClass 等设置选择 AopProxy 实现
AopProxy 通过 getProxy 创建代理对象
图中 Proxy 都实现了 Advised 接口,能够获得关联的切面集合与目标(其实是从 ProxyFactory 取得)
调用代理方法时,会借助 ProxyFactory 将通知统一转为环绕通知:MethodInterceptor
// 1.未setInterfaces 未 setTargetClass CGLIB
// 2.setInterfaces 未 setTargetClass JDKProxy
// 3. setTargetClass CGLIB
http://t.csdn.cn/tPUqD
- interface I1 {
- void foo();
-
- void bar();
- }
-
- static class Target1 implements I1 {
- public void foo() {
- System.out.println("target1 foo");
- }
-
- public void bar() {
- System.out.println("target1 bar");
- }
- }
-
- static class Target2 {
- public void foo() {
- System.out.println("target2 foo");
- }
-
- public void bar() {
- System.out.println("target2 bar");
- }
- }
- import org.aopalliance.intercept.MethodInterceptor;
- import org.springframework.aop.aspectj.AspectJExpressionPointcut;
- import org.springframework.aop.framework.ProxyFactory;
- import org.springframework.aop.support.DefaultPointcutAdvisor;
-
- public class Demo {
- public static void main(String[] args) {
- // 1.添加切入点 pointcut
- AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
- pointcut.setExpression("execution(* foo())");
-
- // 2.添加通知Advice org.aopalliance.intercept.MethodInterceptor
- MethodInterceptor advice = invocation -> {
- System.out.println("before");
- Object proceed = invocation.proceed(); // 调用目标
- System.out.println("after");
- return proceed;
- };
-
- // 3.添加切面 Advisor !! 重要 反向查找就是找一下 advisor 下有 pointcut实现类 的类就可以了!!
- // DefaultPointcutAdvisor 与 AspectJExpressionPointcut 同属于 AbstractGenericPointcutAdvisor
- DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
-
- // 4. 创建代理
- A15.Target1 target = new A15.Target1();
- ProxyFactory proxyFactory = new ProxyFactory();
- proxyFactory.setInterfaces(target.getClass().getInterfaces()); // 如果实现了接口必须setInterfaces ProxyFactory不会自动检测
- // proxyFactory.setTargetClass(target.getClass()); // proxyFactory.getProxy使用的 CGLIB 实现 返回类型需要改为 I1 的子类
- proxyFactory.setTarget(target);
- proxyFactory.addAdvisor(advisor);
- A15.I1 proxy = (A15.I1)proxyFactory.getProxy();
-
- proxy.foo();
- System.out.println(proxy.getClass());
- // spring 代理的实现由两种 JDKProxy 与 CGLIB
- // 1.未setInterfaces 未 setTargetClass CGLIB
- // 2.setInterfaces 未 setTargetClass JDKProxy
- // 3. setTargetClass CGLIB
-
- }
- }

proxyFactory.setInterfaces(target.getClass().getInterfaces()); proxyFactory.setTargetClass(target.getClass());


对使用了注解标注(对整个类型层次结构执行完整搜索,包括超类和实现的接口)的方法进行增强
- StaticMethodMatcherPointcut pt3 = new StaticMethodMatcherPointcut() {
- // 执行静态检查给定方法是否匹配
- @Override
- public boolean matches(Method method, Class> targetClass) {
- // MergedAnnotations可以从任何 Java AnnotatedElement获得。
- // 可以使用不同的搜索策略来定位包含要聚合的注释的相关源元素。
- // 例如, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY将搜索超类和实现的接口。
-
- // 检查方法上是否加了 Transactional 注解
- MergedAnnotations annotations = MergedAnnotations.from(method);
- if (annotations.isPresent(Transactional.class)) {
- return true;
- }
- //
-
- // 查看类上是否加了 Transactional 注解
- annotations = MergedAnnotations.from(targetClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
- if (annotations.isPresent(Transactional.class)) {
- return true;
- }
- return false;
- }
- };
-
- System.out.println(pt3.matches(T1.class.getMethod("foo"), T1.class));
代码参考
org.springframework.aop.framework.autoproxy 包
- package org.springframework.aop.framework.autoproxy;
-
- import org.aopalliance.intercept.MethodInterceptor;
- import org.aopalliance.intercept.MethodInvocation;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.AfterReturning;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.springframework.aop.Advisor;
- import org.springframework.aop.aspectj.AspectJExpressionPointcut;
- import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
- import org.springframework.aop.support.DefaultPointcutAdvisor;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.ConfigurationClassPostProcessor;
- import org.springframework.context.support.GenericApplicationContext;
- import org.springframework.core.annotation.Order;
- import org.springframework.lang.NonNull;
-
- import java.util.List;
-
- public class A17 {
- public static void main(String[] args) {
- GenericApplicationContext context = new GenericApplicationContext();
- context.registerBean("aspect1", Aspect1.class);
- context.registerBean("config", Config.class);
- context.registerBean(ConfigurationClassPostProcessor.class);
- // 属于 BeanPostProcessor 初始化回调前(通过标记接口等填充 bean) 初始化回调后(而使用代理包装 bean)
- context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
- // BeanPostProcessor
- // 创建 -> (*) 依赖注入 -> 初始化 (*)
-
- context.refresh();
- // for (String name : context.getBeanDefinitionNames()) {
- // System.out.println(name);
- // }
-
- /*
- 第一个重要方法 findEligibleAdvisors 找到有【资格】的 Advisors
- a. 有【资格】的 Advisor 一部分是低级的, 可以由自己编写, 如下例中的 advisor3
- b. 有【资格】的 Advisor 另一部分是高级的, 由本章的主角解析 @Aspect 后获得
- */
- AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
- List
advisors = creator.findEligibleAdvisors(Target2.class, "target2"); - /*for (Advisor advisor : advisors) {
- System.out.println(advisor);
- }*/
-
- /*
- 第二个重要方法 wrapIfNecessary
- a. 它内部调用 findEligibleAdvisors, 只要返回集合不空, 则表示需要创建代理
- */
- Object o1 = creator.wrapIfNecessary(new Target1(), "target1", "target1");
- System.out.println(o1.getClass());
- Object o2 = creator.wrapIfNecessary(new Target2(), "target2", "target2");
- System.out.println(o2.getClass());
-
- ((Target1) o1).foo(new Target2("ss"));
- /*
- 学到了什么
- a. 自动代理后处理器 AnnotationAwareAspectJAutoProxyCreator 会帮我们创建代理
- b. 通常代理创建的活在原始对象初始化后执行, 但碰到循环依赖会提前至依赖注入之前执行
- c. 高级的 @Aspect 切面会转换为低级的 Advisor 切面, 理解原理, 大道至简
- */
- }
-
- static class Target1 {
-
-
- public void foo(Target2 ss) {
- System.out.println("target1 foo");
- }
- }
-
- static class Target2 {
- public Target2() {
- }
- public Target2(String ss) {
- this.ss = ss;
- }
-
- @NonNull
- private String ss;
-
- public String getSs() {
- return ss;
- }
-
- public void setSs(String ss) {
- this.ss = ss;
- }
-
- public void bar() {
- System.out.println("target2 bar");
- }
- }
-
- @Aspect // 高级切面类
- @Order(2)
- static class Aspect1 {
- @AfterReturning("execution(* foo(*))")
- public void before1(JoinPoint joinPoint) {
- System.out.println("aspect1 before1..." + (MethodInvocation)joinPoint);
- }
-
- @Before("execution(* foo())")
- public void before2() {
- System.out.println("aspect1 before2...");
- }
- }
-
- @Configuration
- static class Config {
- @Bean // 低级切面
- // @Order(1) p配置在此地方不生效
- public Advisor advisor3(MethodInterceptor advice3) {
- AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
- pointcut.setExpression("execution(* foo())");
- DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice3);
- advisor.setOrder(1);
- return advisor;
- }
- @Bean
- public MethodInterceptor advice3() {
- return invocation -> {
- System.out.println("advice3 before...");
- Object result = invocation.proceed();
- System.out.println("advice3 after...");
- return result;
- };
- }
- }
-
- }
AnnotationAwareAspectJAutoProxyCreator 的作用
将高级 @Aspect 切面统一为低级 Advisor 切面
在合适的时机创建代理
findEligibleAdvisors 找到有【资格】的 Advisors
有【资格】的 Advisor 一部分是低级的, 可以由自己编写, 如本例 A17 中的 advisor3
有【资格】的 Advisor 另一部分是高级的, 由解析 @Aspect 后获得
wrapIfNecessary
它内部调用 findEligibleAdvisors, 只要返回集合不空, 则表示需要创建代理
它的调用时机通常在原始对象初始化后执行, 但碰到循环依赖会提前至依赖注入之前执行
代码参考
org.springframework.aop.framework.autoproxy.A17_1
- static class Bean1 {
- public void foo() {
-
- }
- public Bean1() {
- System.out.println("Bean1()");
- }
- // 取消循环依赖就将该方法注释掉即可
- @Autowired public void setBean2(Bean2 bean2) {
- System.out.println("Bean1 setBean2(bean2) class is: " + bean2.getClass());
- }
- @PostConstruct public void init() {
- System.out.println("Bean1 init()");
- }
- }
-
- static class Bean2 {
- public Bean2() {
- System.out.println("Bean2()");
- }
- @Autowired public void setBean1(Bean1 bean1) {
- System.out.println("Bean2 setBean1(bean1) class is: " + bean1.getClass());
- }
- @PostConstruct public void init() {
- System.out.println("Bean2 init()");
- }
- }
注意 “Creating implicit proxy for bean 'bean1'”意思是增强了.

Bean2 setBean1依赖注入Bean1 代理($Bean1)增强后($$EnhancerBySpringCGLIB)的对象

// 工厂方法配置
- @Configuration
- static class Config {
- @Bean // 解析 @Aspect、产生代理
- public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
- return new AnnotationAwareAspectJAutoProxyCreator();
- }
-
- @Bean // 解析 @Autowired
- public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor() {
- return new AutowiredAnnotationBeanPostProcessor();
- }
-
- @Bean // 解析 @PostConstruct
- public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {
- return new CommonAnnotationBeanPostProcessor();
- }
-
- @Bean
- public Advisor advisor(MethodInterceptor advice) {
- AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
- pointcut.setExpression("execution(* foo())");
- return new DefaultPointcutAdvisor(pointcut, advice);
- }
-
- @Bean
- public MethodInterceptor advice() {
- return (MethodInvocation invocation) -> {
- System.out.println("before...");
- return invocation.proceed();
- };
- }
-
- @Bean
- public Bean1 bean1() {
- return new Bean1();
- }
-
- @Bean
- public Bean2 bean2() {
- return new Bean2();
- }
- }
// 主方法调用
- public static void main(String[] args) {
- GenericApplicationContext context = new GenericApplicationContext();
- context.registerBean(ConfigurationClassPostProcessor.class);
- context.registerBean(Config.class);
- context.refresh();
- context.close();
- // 创建 -> (*) 依赖注入 -> 初始化 (*)
- /*
- 学到了什么
- a. 代理的创建时机
- 1. 初始化之后 (无循环依赖时)
- 2. 实例创建后, 依赖注入前 (有循环依赖时), 并暂存于二级缓存
- b. 依赖注入与初始化不应该被增强, 仍应被施加于原始对象
- */
- }
创建 -> (1.2) 依赖注入 -> 初始化 (1.1)
代理的创建时机
无循环依赖时:初始化之后
有循环依赖时:实例创建后, 依赖注入前 , 并暂存于二级缓存
依赖注入与初始化不应该被增强, 仍 应被施加于原始对象
基础的应用场景是 配置类中(标注了@Aspect注解的多个类 声明了多个切面 默认的执行顺序是Bean注册的顺序),但我想自定义 切面拦截的顺序。
@Order 放在类上可以生效。org.aspectj.lang.annotation类下面的注解不是@Bean的子类。所以不能定义拦截的顺序。
对于实现了org.springframework.core.Ordered接口的来来说。配置此类的order属性即可。


高级切面转低级切面类 + 通知统一转换为环绕通知 MethodInterceptor + 创建并执行调用链 (环绕通知s + 目标)
- import org.aopalliance.intercept.MethodInvocation;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.AfterReturning;
- import org.aspectj.lang.annotation.AfterThrowing;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Before;
- import org.springframework.aop.Advisor;
- import org.springframework.aop.aspectj.*;
- import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
- import org.springframework.aop.support.DefaultPointcutAdvisor;
-
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.List;
-
- public class A18 {
-
- static class Aspect {
- @Before("execution(* foo())")
- public void before1() {
- System.out.println("before1");
- }
-
- @Before("execution(* foo())")
- public void before2() {
- System.out.println("before2");
- }
-
- public void after() {
- System.out.println("after");
- }
-
- @AfterReturning("execution(* foo())")
- public void afterReturning() {
- System.out.println("afterReturning");
- }
-
- @AfterThrowing("execution(* foo())")
- public void afterThrowing(Exception e) {
- System.out.println("afterThrowing " + e.getMessage());
- }
-
- @Around("execution(* foo())")
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- try {
- System.out.println("around...before");
- return pjp.proceed();
- } finally {
- System.out.println("around...after");
- }
- }
- }
-
- static class Target {
- public void foo() {
- System.out.println("target foo");
- }
- }
-
- @SuppressWarnings("all")
- public static void main(String[] args) throws Throwable {
-
- AspectInstanceFactory factory = new SingletonAspectInstanceFactory(new Aspect());
- // 1. 高级切面转低级切面类
- List
list = new ArrayList<>(); - for (Method method : Aspect.class.getDeclaredMethods()) {
- if (method.isAnnotationPresent(Before.class)) {
- // 解析切点
- String expression = method.getAnnotation(Before.class).value();
- AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
- pointcut.setExpression(expression);
- // 通知类
- AspectJMethodBeforeAdvice advice = new AspectJMethodBeforeAdvice(method, pointcut, factory);
- // 切面
- Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
- list.add(advisor);
- } else if (method.isAnnotationPresent(AfterReturning.class)) {
- // 解析切点
- String expression = method.getAnnotation(AfterReturning.class).value();
- AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
- pointcut.setExpression(expression);
- // 通知类
- AspectJAfterReturningAdvice advice = new AspectJAfterReturningAdvice(method, pointcut, factory);
- // 切面
- Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
- list.add(advisor);
- } else if (method.isAnnotationPresent(Around.class)) {
- // 解析切点
- String expression = method.getAnnotation(Around.class).value();
- AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
- pointcut.setExpression(expression);
- // 通知类
- AspectJAroundAdvice advice = new AspectJAroundAdvice(method, pointcut, factory);
- // 切面
- Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
- list.add(advisor);
- }
- }
- for (Advisor advisor : list) {
- // 还要为低级的切面进行排序
- System.out.println(advisor);
- }
-
- /*
- @Before 前置通知会被转换为下面原始的 AspectJMethodBeforeAdvice 形式, 该对象包含了如下信息
- a. 通知代码从哪儿来
- b. 切点是什么
- c. 通知对象如何创建, 本例共用同一个 Aspect 对象
- 类似的通知还有
- 1. AspectJAroundAdvice (环绕通知)
- 2. AspectJAfterReturningAdvice
- 3. AspectJAfterThrowingAdvice (环绕通知)
- 4. AspectJAfterAdvice (环绕通知)
- */
-
- // 2. 通知统一转换为环绕通知 MethodInterceptor
- /*
- 其实无论 ProxyFactory 基于哪种方式创建代理, 最后干活(调用 advice)的是一个 MethodInvocation 对象
- a. 因为 advisor 有多个, 且一个套一个调用, 因此需要一个调用链对象, 即 MethodInvocation
- b. MethodInvocation 要知道 advice 有哪些, 还要知道目标, 调用次序如下
- !.将 MethodInvocation 放入当前线程
- |-> before1 ----------------------------------- 从当前线程获取 MethodInvocation
- | |
- | |-> before2 -------------------- | 从当前线程获取 MethodInvocation
- | | | |
- | | |-> target ------ 目标 advice2 advice1
- | | | |
- | |-> after2 --------------------- |
- | |
- |-> after1 ------------------------------------
- c. 从上图看出, 环绕通知才适合作为 advice, 因此其他 before、afterReturning 都会被转换成环绕通知
- d. 统一转换为环绕通知, 体现的是设计模式中的适配器模式
- - 对外是为了方便使用要区分 before、afterReturning
- - 对内统一都是环绕通知, 统一用 MethodInterceptor 表示
- 此步获取所有执行时需要的 advice (静态)
- a. 即统一转换为 MethodInterceptor 环绕通知, 这体现在方法名中的 Interceptors 上
- b. 适配如下
- - MethodBeforeAdviceAdapter 将 @Before AspectJMethodBeforeAdvice 适配为 MethodBeforeAdviceInterceptor
- - AfterReturningAdviceAdapter 将 @AfterReturning AspectJAfterReturningAdvice 适配为 AfterReturningAdviceInterceptor
- */
- Target target = new Target();
- ProxyFactory proxyFactory = new ProxyFactory();
- proxyFactory.setTarget(target);
-
- // !.准备把 MethodInvocation 放入当前线程,需要放在环绕通知的最外层,用于暴露 MethodInvocation 的一个工具类
- // 是单例的 使用的私有构造
- proxyFactory.addAdvice(ExposeInvocationInterceptor.INSTANCE);
- proxyFactory.addAdvisors(list);
-
- System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- List
- for (Object o : methodInterceptorList) {
- System.out.println(o);
- }
-
- System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- // 3. 创建并执行调用链 (环绕通知s + 目标)
- MethodInvocation methodInvocation = new ReflectiveMethodInvocation(
- null, target, Target.class.getMethod("foo"), new Object[0], Target.class, methodInterceptorList
- );
- methodInvocation.proceed();
-
-
-
- /*
- 学到了什么
- a. 无参数绑定的通知如何被调用
- b. MethodInvocation 编程技巧: 拦截器、过滤器等等实现都与此类似
- c. 适配器模式在 Spring 中的体现
- */
-
- }
- }

代理对象调用流程如下(以 JDK 动态代理实现为例)
从 ProxyFactory 获得 Target 和环绕通知链,根据他俩创建 MethodInvocation,简称 mi
首次执行 mi.proceed() 发现有下一个环绕通知,调用它的 invoke(mi)
进入环绕通知1,执行前增强,再次调用 mi.proceed() 发现有下一个环绕通知,调用它的 invoke(mi)
进入环绕通知2,执行前增强,调用 mi.proceed() 发现没有环绕通知,调用 mi.invokeJoinPoint() 执行目标方法
目标方法执行结束,将结果返回给环绕通知2,执行环绕通知2 的后增强
环绕通知2继续将结果返回给环绕通知1,执行环绕通知1 的后增强
环绕通知1返回最终的结果
图中不同颜色对应一次环绕通知或目标的调用起始至终结
- /*
- 模拟调用链过程, 是一个简单的递归过程
- 1. proceed() 方法调用链中下一个环绕通知
- 2. 每个环绕通知内部继续调用 proceed()
- 3. 调用到没有更多通知了, 就调用目标方法
- */
- public class A18_1 {
-
- static class Target {
- public void foo() {
- System.out.println("Target.foo()");
- }
- }
-
- static class Advice1 implements MethodInterceptor {
- @Override
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.println("Advice1.before()");
- Object result = invocation.proceed();// 调用下一个通知或目标
- System.out.println("Advice1.after()");
- return result;
- }
- }
-
- static class Advice2 implements MethodInterceptor {
- @Override
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.println("Advice2.before()");
- Object result = invocation.proceed();// 调用下一个通知或目标
- System.out.println("Advice2.after()");
- return result;
- }
- }
-
-
- static class MyInvocation implements MethodInvocation {
- private Object target; // 1
- private Method method;
- private Object[] args;
- List
methodInterceptorList; // 2 - private int count = 1; // 调用次数
-
- public MyInvocation(Object target, Method method, Object[] args, List
methodInterceptorList) { - this.target = target;
- this.method = method;
- this.args = args;
- this.methodInterceptorList = methodInterceptorList;
- }
-
- @Override
- public Method getMethod() {
- return method;
- }
-
- @Override
- public Object[] getArguments() {
- return args;
- }
-
- @Override
- public Object proceed() throws Throwable { // 调用每一个环绕通知, 调用目标
- if (count > methodInterceptorList.size()) {
- // 调用目标, 返回并结束递归
- return method.invoke(target, args);
- }
- // 逐一调用通知, count + 1
- MethodInterceptor methodInterceptor = methodInterceptorList.get(count++ - 1);
- return methodInterceptor.invoke(this);
- }
-
- @Override
- public Object getThis() {
- return target;
- }
-
- @Override
- public AccessibleObject getStaticPart() {
- return method;
- }
- }
-
- public static void main(String[] args) throws Throwable {
- Target target = new Target();
- List
list = List.of( - new Advice1(),
- new Advice2()
- );
- MyInvocation invocation = new MyInvocation(target, Target.class.getMethod("foo"), new Object[0], list);
- invocation.proceed();
- }
- }

注解介绍: Spring AOP切点表达式用法总结 - 爱宝贝丶 - 博客园 (cnblogs.com)
切面形参介绍:@Aspect 切面注解使用 - 秃了也变强了 - 博客园 (cnblogs.com)
拦截器执行的顺序:
- try {
- Object result = null;
- try {
- System.out.println("@Around通知start");
- System.out.println("@Before通知!");
- result = service4.say("路人");
- System.out.println("@Around绕通知end");
- return result;
- } finally {
- System.out.println("@After通知!");
- }
- System.out.println("@AfterReturning通知!");
- return retVal;
- } catch (Throwable ex) {
- System.out.println("@AfterThrowing通知!");
- //继续抛出异常
- throw ex;
- }