代码参考项目 demo6_advanced_aspectj_01
收获
编译器也能修改 class 实现增强
编译器增强能突破代理仅能通过方法重写增强的限制:可以对构造方法、静态方法等实现增强
项目地址:demo6_advanced_aspectj_01https://github.com/LJay997/demo6_advanced_aspectj_01
查看IDEA 编译的class文件可看出ajc帮我们修改了源码实现了增强静态方法
代码参考项目 demo6_advanced_aspectj_02
收获
类加载时可以通过 agent 修改 class 实现增强
demo6_advanced_aspectj_02https://github.com/LJay997/demo6_advanced_aspectj_02项目地址:[email protected]:LJay997/demo6_advanced_aspectj_02.git
Arthashttps://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(在哪些地方增强)
通知:典型接口为 MethodInterceptor 代表环绕通知(增强具体要做的事情)
切面: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
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注册的顺序),但我想自定义 切面拦截的顺序。
1.定义@Aspect类(高级切面类)的顺序 使用 @Order注解
@Order 放在类上可以生效。org.aspectj.lang.annotation类下面的注解不是@Bean的子类。所以不能定义拦截的顺序。
2.定义@Configuration (低级切面方法)的顺序。
对于实现了org.springframework.core.Ordered接口的来来说。配置此类的order属性即可。