AOP编译器增强
使用AspectJ的ajc编译器
进行AOP增强。在编译阶段对字节码进行增强。 编写一个SpringBoot主类:
@SpringBootApplication
public class AspectTest {
public static void main ( String [ ] args) {
ConfigurableApplicationContext run = SpringApplication . run ( AspectTest . class , args) ;
MyService myService = run. getBean ( MyService . class ) ;
System . out. println ( myService. getClass ( ) ) ;
myService. foo ( ) ;
run. close ( ) ;
}
}
service类:
@Service
public class MyService {
public void foo ( ) {
System . out. println ( "myService foo..." ) ;
}
}
Aspect进行增强:
@Aspect
public class MyAspect {
@Before ( "execution(* aop.service.MyService.foo())" )
public void before ( ) {
System . out. println ( "before......" ) ;
}
}
加入aspectJ的maven插件,使用ajc编译器对字节码文件进行增强。 (直接运行可能不会进行增强,因为idea使用的是javac编译器)
< 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>
< goal> compile</ goal>
< goal> test-compile</ goal>
</ goals>
</ execution>
</ executions>
</ plugin>
需要使用maven的compile进行编译,因为ajc编译器插件在maven中配置的。
就可以看到class文件被编译器增强了。
所以我们是在编译的使用进行增强,而不是Spring的动态代理增强。可以直接调用该方法。
@SpringBootApplication
public class AspectTest {
public static void main ( String [ ] args) {
new MyService ( ) . foo ( ) ;
}
}
Spring动态代理不能对static静态方法进行代理,而编译器增强可以。
AOP在运行时增强
使用javaagent
在java运行时,进行aop增强。注释掉上面的maven编译时插件。 需要增强的Service类
@Service
public class MyService {
public void foo ( ) {
System . out. println ( "myService foo..." ) ;
bar ( ) ;
}
public void bar ( ) {
System . out. println ( "myService bar..." ) ;
}
}
切面类
@Aspect
public class MyAspect {
@Before ( "execution(* aop.service.MyService.*())" )
public void before ( ) {
System . out. println ( "before......" ) ;
}
}
启动类
@SpringBootApplication
public class AspectTest {
public static void main ( String [ ] args) {
ConfigurableApplicationContext run = SpringApplication . run ( AspectTest . class , args) ;
MyService myService = run. getBean ( MyService . class ) ;
System . out. println ( myService. getClass ( ) ) ;
myService. foo ( ) ;
}
}
加入JVM参数javaagent,使用aspectj的jar包:-javaagent:F:/program/apache-maven-3.5.4/repository/org/aspectj/aspectjweaver/1.9.7/aspectjweaver-1.9.7.jar
。 还需要在resource目录下新建META-INF/aop.xml文件。
<! DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd" >
< aspectj>
< aspects>
< aspect name = " aop.aop.MyAspect" />
< weaver options = " -verbose -showWeaveInfo" >
< include within = " aop..*" />
</ weaver>
</ aspects>
</ aspectj>
运行启动类,可以看到两个方法被增强。
但是查看字节码文件,并没有在字节码文件中体现增强。
所以并没有在编译器进行增强,而是在运行期间
对字节码文件进行了增强。 使用阿里巴巴的arthas工具
对运行期的字节码进行反编译查看。 下载arthas,使用arthas-boot.jar这个jar包启动,java -jar arthas-boot.jar
。 使用help可以查看命令帮助。 使用jad aop.service.MyService
命令对MyService的字节码进行反编译 ,可以看到aspectj在运行期间修改了字节码文件,对方法进行了增强。
使用运行期间增强,在方法嵌套调用时,也可以对每个方法进行增强 。但是,生成代理对象就不能对嵌套方法进行增强。动态替换字节码,参考美团技术:https://tech.meituan.com/2019/09/05/java-bytecode-enhancement.html
JDK增强
public class JdkProxy {
interface Foo {
void foo ( ) ;
}
static class Target implements Foo {
@Override
public void foo ( ) {
System . out. println ( "foo..." ) ;
}
}
public static void main ( String [ ] args) {
ClassLoader classLoader = JdkProxy . class . getClassLoader ( ) ;
Target target = new Target ( ) ;
Foo proxyInstance = ( Foo ) Proxy . newProxyInstance ( classLoader, new Class [ ] { Foo . class } , ( proxy, method, args1) -> {
System . out. println ( "before" ) ;
Object invoke = method. invoke ( target, args1) ;
System . out. println ( "after" ) ;
return invoke;
} ) ;
proxyInstance. foo ( ) ;
}
}
Cglib增强
Cglib创建的是子类 对父类进行增强,所以如果父类定义为final
,创建子类就会报错。
如果需要增强的方法定义为final ,那么方法无法被增强。
public class CglibProxy {
static final class Target {
public void foo ( ) {
System . out. println ( "foo..." ) ;
}
}
public static void main ( String [ ] args) {
Target target = new Target ( ) ;
Target proxy = ( Target ) Enhancer . create ( Target . class , new MethodInterceptor ( ) {
@Override
public Object intercept ( Object o, Method method, Object [ ] args, MethodProxy methodProxy) throws Throwable {
System . out. println ( "before" ) ;
Object invoke = methodProxy. invokeSuper ( o, args) ;
System . out. println ( "before" ) ;
return invoke;
}
} ) ;
proxy. foo ( ) ;
}
}
自定义JDK代理
jdk代理是基于接口的。
public class MyJdkProxy {
interface Foo {
void foo ( ) ;
int bar ( ) ;
}
static class Target implements Foo {
public void foo ( ) {
System . out. println ( "foo..." ) ;
}
@Override
public int bar ( ) {
System . out. println ( "bar..." ) ;
return 100 ;
}
}
interface InvocationHandler {
Object invoke ( Object proxy, Method method, Object [ ] args) throws Throwable ;
}
public static void main ( String [ ] args) {
Foo proxy = new $Proxy0 ( new InvocationHandler ( ) {
@Override
public Object invoke ( Object proxy, Method method, Object [ ] args) throws Throwable {
System . out. println ( "before" ) ;
if ( method. getName ( ) . equals ( "bar" ) ) {
Object invoke = method. invoke ( new Target ( ) , args) ;
System . out. println ( ( int ) invoke) ;
return ( int ) invoke + 50 ;
}
return null ;
}
} ) ;
proxy. foo ( ) ;
System . out. println ( proxy. bar ( ) ) ;
}
}
自定义代理类
public class $Proxy0 implements MyJdkProxy. Foo {
private final MyJdkProxy. InvocationHandler invocationHandler;
static Method foo;
static Method bar;
static {
try {
foo = MyJdkProxy. Target . class . getMethod ( "foo" ) ;
bar = MyJdkProxy. Target . class . getMethod ( "bar" ) ;
} catch ( NoSuchMethodException e) {
throw new NoSuchMethodError ( e. getMessage ( ) ) ;
}
}
public $Proxy0 ( MyJdkProxy. InvocationHandler invocationHandler) {
this . invocationHandler = invocationHandler;
}
public void foo ( ) {
try {
Method foo = MyJdkProxy. Foo . class . getMethod ( "foo" ) ;
invocationHandler. invoke ( this , foo, new Object [ 0 ] ) ;
} catch ( RuntimeException | Error e) {
throw e;
} catch ( Throwable e) {
throw new UndeclaredThrowableException ( e) ;
}
}
@Override
public int bar ( ) {
try {
Method bar = MyJdkProxy. Foo . class . getMethod ( "bar" ) ;
Object invoke = invocationHandler. invoke ( this , bar, new Object [ 0 ] ) ;
return ( int ) invoke;
} catch ( RuntimeException | Error e) {
throw e;
} catch ( Throwable e) {
throw new UndeclaredThrowableException ( e) ;
}
}
}
arthas查看JDK生成的代理类
使用原来JDK代理的demo,和arthas工具反编译代理类,查看jdk生成的代理类。并且程序不能停止。
public class JdkProxy {
interface Foo {
void foo ( ) ;
}
static class Target implements Foo {
@Override
public void foo ( ) {
System . out. println ( "foo..." ) ;
}
}
public static void main ( String [ ] args) throws IOException {
ClassLoader classLoader = JdkProxy . class . getClassLoader ( ) ;
Target target = new Target ( ) ;
Foo proxyInstance = ( Foo ) Proxy . newProxyInstance ( classLoader, new Class [ ] { Foo . class } , ( proxy, method, args1) -> {
System . out. println ( "before" ) ;
Object invoke = method. invoke ( target, args1) ;
System . out. println ( "after" ) ;
return invoke;
} ) ;
System . out. println ( proxyInstance. getClass ( ) ) ;
proxyInstance. foo ( ) ;
System . in. read ( ) ;
}
}
打开arthas工具。java -jar arthas-boot.jar
。
连接上java程序后,输入jad aop.service.$Proxy0
就可以反编译该代理类。
ClassLoader :
+ - sun. misc. Launcher $AppClassLoader @18b4aac2
+ - sun. misc. Launcher $ExtClassLoader @2bdd5e07
Location :
package aop. service ;
import aop. service. JdkProxy ;
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 JdkProxy. Foo {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0 ( InvocationHandler invocationHandler) {
super ( invocationHandler) ;
}
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 ( "aop.service.JdkProxy$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 ( ) ) ;
}
}
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 hashCode ( ) {
try {
return ( Integer ) this . h. invoke ( this , m0, null ) ;
}
catch ( Error | RuntimeException throwable) {
throw throwable;
}
catch ( Throwable throwable) {
throw new UndeclaredThrowableException ( throwable) ;
}
}
public final void foo ( ) {
try {
this . h. invoke ( this , m3, null ) ;
return ;
}
catch ( Error | RuntimeException throwable) {
throw throwable;
}
catch ( Throwable throwable) {
throw new UndeclaredThrowableException ( throwable) ;
}
}
}
继承了Proxy
类,因为InvocationHandler
是Proxy类的成员变量,从父类继承过来。 JDK生成的代理类,没有经过源码 -> 编译 -> 字节码
的阶段。而是直接生成了代理类的字节码 ,我们得到的是字节码反编译后的代码。 运行期间动态生成字节码的底层技术叫ASM,广泛应用于Spring和JDK等框架。
Idea安装ASM插件生成字节码
JDK生成代理类,没有经过源码 -> 编译 -> 字节码
的阶段,而是直接生成了代理类的字节码 。 运行期间动态生成字节码的技术叫ASM
。 在Idea安装一个ASM的插件,ASM Bytecode Outline
。
定义接口,和手写代理类
public interface Foo {
void foo ( ) ;
}
public class $Proxy0 extends Proxy implements Foo {
static Method foo;
static {
try {
foo = Foo . class . getMethod ( "foo" ) ;
} catch ( NoSuchMethodException e) {
throw new NoSuchMethodError ( e. getMessage ( ) ) ;
}
}
protected $Proxy0 ( InvocationHandler h) {
super ( h) ;
}
@Override
public void foo ( ) {
try {
System . out. println ( "before..." ) ;
Object invoke = this . h. invoke ( this , foo, new Object [ ] { } ) ;
} catch ( Throwable e) {
throw new UndeclaredThrowableException ( e) ;
}
}
}
将两个类编译一下。
然后使用ASM的插件,将代理类的Java源码转化为ASM的代码 。
第二个就是ASM的API可以生成代理类的字节码。
将该类粘贴出来,并导入Spring相关ASM的包
public class $Proxy0Dump implements Opcodes {
public static byte [ ] dump ( ) throws Exception {
ClassWriter cw = new ClassWriter ( 0 ) ;
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw. visit ( 52 , ACC_PUBLIC + ACC_SUPER, "aop/my/asm/$Proxy0" , null , "java/lang/reflect/Proxy" , new String [ ] { "aop/my/asm/Foo" } ) ;
cw. visitSource ( "$Proxy0.java" , null ) ;
{
fv = cw. visitField ( ACC_STATIC, "foo" , "Ljava/lang/reflect/Method;" , null , null ) ;
fv. visitEnd ( ) ;
}
{
mv = cw. visitMethod ( ACC_PROTECTED, "<init>" , "(Ljava/lang/reflect/InvocationHandler;)V" , null , null ) ;
mv. visitCode ( ) ;
Label l0 = new Label ( ) ;
mv. visitLabel ( l0) ;
mv. visitLineNumber ( 22 , l0) ;
mv. visitVarInsn ( ALOAD, 0 ) ;
mv. visitVarInsn ( ALOAD, 1 ) ;
mv. visitMethodInsn ( INVOKESPECIAL, "java/lang/reflect/Proxy" , "<init>" , "(Ljava/lang/reflect/InvocationHandler;)V" , false ) ;
Label l1 = new Label ( ) ;
mv. visitLabel ( l1) ;
mv. visitLineNumber ( 23 , l1) ;
mv. visitInsn ( RETURN) ;
Label l2 = new Label ( ) ;
mv. visitLabel ( l2) ;
mv. visitLocalVariable ( "this" , "Laop/my/asm/$Proxy0;" , null , l0, l2, 0 ) ;
mv. visitLocalVariable ( "h" , "Ljava/lang/reflect/InvocationHandler;" , null , l0, l2, 1 ) ;
mv. visitMaxs ( 2 , 2 ) ;
mv. visitEnd ( ) ;
}
{
mv = cw. visitMethod ( ACC_PUBLIC, "foo" , "()V" , null , null ) ;
mv. visitCode ( ) ;
Label l0 = new Label ( ) ;
Label l1 = new Label ( ) ;
Label l2 = new Label ( ) ;
mv. visitTryCatchBlock ( l0, l1, l2, "java/lang/Throwable" ) ;
mv. visitLabel ( l0) ;
mv. visitLineNumber ( 28 , l0) ;
mv. visitFieldInsn ( GETSTATIC, "java/lang/System" , "out" , "Ljava/io/PrintStream;" ) ;
mv. visitLdcInsn ( "before..." ) ;
mv. visitMethodInsn ( INVOKEVIRTUAL, "java/io/PrintStream" , "println" , "(Ljava/lang/String;)V" , false ) ;
Label l3 = new Label ( ) ;
mv. visitLabel ( l3) ;
mv. visitLineNumber ( 29 , l3) ;
mv. visitVarInsn ( ALOAD, 0 ) ;
mv. visitFieldInsn ( GETFIELD, "aop/my/asm/$Proxy0" , "h" , "Ljava/lang/reflect/InvocationHandler;" ) ;
mv. visitVarInsn ( ALOAD, 0 ) ;
mv. visitFieldInsn ( GETSTATIC, "aop/my/asm/$Proxy0" , "foo" , "Ljava/lang/reflect/Method;" ) ;
mv. visitInsn ( ICONST_0) ;
mv. visitTypeInsn ( ANEWARRAY, "java/lang/Object" ) ;
mv. visitMethodInsn ( INVOKEINTERFACE, "java/lang/reflect/InvocationHandler" , "invoke" , "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;" , true ) ;
mv. visitVarInsn ( ASTORE, 1 ) ;
mv. visitLabel ( l1) ;
mv. visitLineNumber ( 32 , l1) ;
Label l4 = new Label ( ) ;
mv. visitJumpInsn ( GOTO, l4) ;
mv. visitLabel ( l2) ;
mv. visitLineNumber ( 30 , l2) ;
mv. visitFrame ( Opcodes . F_SAME1, 0 , null , 1 , new Object [ ] { "java/lang/Throwable" } ) ;
mv. visitVarInsn ( ASTORE, 1 ) ;
Label l5 = new Label ( ) ;
mv. visitLabel ( l5) ;
mv. visitLineNumber ( 31 , l5) ;
mv. visitTypeInsn ( NEW, "java/lang/reflect/UndeclaredThrowableException" ) ;
mv. visitInsn ( DUP) ;
mv. visitVarInsn ( ALOAD, 1 ) ;
mv. visitMethodInsn ( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException" , "<init>" , "(Ljava/lang/Throwable;)V" , false ) ;
mv. visitInsn ( ATHROW) ;
mv. visitLabel ( l4) ;
mv. visitLineNumber ( 33 , l4) ;
mv. visitFrame ( Opcodes . F_SAME, 0 , null , 0 , null ) ;
mv. visitInsn ( RETURN) ;
Label l6 = new Label ( ) ;
mv. visitLabel ( l6) ;
mv. visitLocalVariable ( "e" , "Ljava/lang/Throwable;" , null , l5, l4, 1 ) ;
mv. visitLocalVariable ( "this" , "Laop/my/asm/$Proxy0;" , null , l0, l6, 0 ) ;
mv. visitMaxs ( 4 , 2 ) ;
mv. visitEnd ( ) ;
}
{
mv = cw. visitMethod ( ACC_STATIC, "<clinit>" , "()V" , null , null ) ;
mv. visitCode ( ) ;
Label l0 = new Label ( ) ;
Label l1 = new Label ( ) ;
Label l2 = new Label ( ) ;
mv. visitTryCatchBlock ( l0, l1, l2, "java/lang/NoSuchMethodException" ) ;
mv. visitLabel ( l0) ;
mv. visitLineNumber ( 15 , l0) ;
mv. visitLdcInsn ( Type . getType ( "Laop/my/asm/Foo;" ) ) ;
mv. visitLdcInsn ( "foo" ) ;
mv. visitInsn ( ICONST_0) ;
mv. visitTypeInsn ( ANEWARRAY, "java/lang/Class" ) ;
mv. visitMethodInsn ( INVOKEVIRTUAL, "java/lang/Class" , "getMethod" , "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;" , false ) ;
mv. visitFieldInsn ( PUTSTATIC, "aop/my/asm/$Proxy0" , "foo" , "Ljava/lang/reflect/Method;" ) ;
mv. visitLabel ( l1) ;
mv. visitLineNumber ( 18 , l1) ;
Label l3 = new Label ( ) ;
mv. visitJumpInsn ( GOTO, l3) ;
mv. visitLabel ( l2) ;
mv. visitLineNumber ( 16 , l2) ;
mv. visitFrame ( Opcodes . F_SAME1, 0 , null , 1 , new Object [ ] { "java/lang/NoSuchMethodException" } ) ;
mv. visitVarInsn ( ASTORE, 0 ) ;
Label l4 = new Label ( ) ;
mv. visitLabel ( l4) ;
mv. visitLineNumber ( 17 , l4) ;
mv. visitTypeInsn ( NEW, "java/lang/NoSuchMethodError" ) ;
mv. visitInsn ( DUP) ;
mv. visitVarInsn ( ALOAD, 0 ) ;
mv. visitMethodInsn ( INVOKEVIRTUAL, "java/lang/NoSuchMethodException" , "getMessage" , "()Ljava/lang/String;" , false ) ;
mv. visitMethodInsn ( INVOKESPECIAL, "java/lang/NoSuchMethodError" , "<init>" , "(Ljava/lang/String;)V" , false ) ;
mv. visitInsn ( ATHROW) ;
mv. visitLabel ( l3) ;
mv. visitLineNumber ( 19 , l3) ;
mv. visitFrame ( Opcodes . F_SAME, 0 , null , 0 , null ) ;
mv. visitInsn ( RETURN) ;
mv. visitLocalVariable ( "e" , "Ljava/lang/NoSuchMethodException;" , null , l4, l3, 0 ) ;
mv. visitMaxs ( 3 , 1 ) ;
mv. visitEnd ( ) ;
}
cw. visitEnd ( ) ;
return cw. toByteArray ( ) ;
}
}
调用该类的dump静态方法,就可以生成字节码文件。
public class TestProxy {
public static void main ( String [ ] args) throws Exception {
byte [ ] dump = $Proxy0Dump . dump ( ) ;
FileOutputStream fileOutputStream = new FileOutputStream ( "proxy.class" ) ;
fileOutputStream. write ( dump, 0 , dump. length) ;
fileOutputStream. close ( ) ;
}
}
我们可以看到字节码就是我们编写的代理类。
动态加载字节码
public class TestProxy {
public static void main ( String [ ] args) throws Exception {
byte [ ] dump = $Proxy0Dump . dump ( ) ;
ClassLoader classLoader = new ClassLoader ( ) {
@Override
protected Class < ? > findClass ( String name) throws ClassNotFoundException {
System . out. println ( name) ;
return super . defineClass ( name, dump, 0 , dump. length) ;
}
} ;
Class < ? > proxyClass = classLoader. loadClass ( "aop.my.asm.$Proxy0" ) ;
Constructor < ? > constructor = proxyClass. getDeclaredConstructor ( InvocationHandler . class ) ;
constructor. setAccessible ( true ) ;
Foo proxy = ( Foo ) constructor. newInstance ( new InvocationHandler ( ) {
@Override
public Object invoke ( Object proxy, Method method, Object [ ] args) throws Throwable {
System . out. println ( "step1..." ) ;
System . out. println ( "调用目标方法" ) ;
return null ;
}
} ) ;
proxy. foo ( ) ;
}
}
JDK底层对方法反射执行的优化
JDK代理中,使用了很多反射调用方法method.invoke()
。JDK底层对反射的执行有一定的优化。 测试代码:
public class ReflectOptimize {
public static void main ( String [ ] args) throws NoSuchMethodException , InvocationTargetException , IllegalAccessException , IOException {
TestReflect testReflect = new TestReflect ( ) ;
Method foo = TestReflect . class . getMethod ( "foo" , int . class ) ;
for ( int i = 1 ; i <= 16 ; i++ ) {
foo. invoke ( testReflect, i) ;
show ( foo, i) ;
}
System . in. read ( ) ;
}
private static void show ( Method foo, int i) throws IllegalAccessException {
try {
Class < ? extends Method > aClass = foo. getClass ( ) ;
Field methodAccessor = aClass. getDeclaredField ( "methodAccessor" ) ;
methodAccessor. setAccessible ( true ) ;
MethodAccessor accessor = ( MethodAccessor ) methodAccessor. get ( foo) ;
if ( accessor != null ) {
Class < ? extends MethodAccessor > aClass1 = accessor. getClass ( ) ;
Field delegate = aClass1. getDeclaredField ( "delegate" ) ;
delegate. setAccessible ( true ) ;
Object impl = delegate. get ( accessor) ;
System . out. println ( "i = " + i + " = , " + impl) ;
}
} catch ( NoSuchFieldException e) {
e. printStackTrace ( ) ;
}
}
static class TestReflect {
public void foo ( int i) {
System . out. println ( "i = " + i + ", foo..." ) ;
}
}
}
输出如下:
i = 1, foo...
i = 1 = , sun.reflect.NativeMethodAccessorImpl@7291c18f
i = 2, foo...
i = 2 = , sun.reflect.NativeMethodAccessorImpl@7291c18f
i = 3, foo...
i = 3 = , sun.reflect.NativeMethodAccessorImpl@7291c18f
...
i = 15, foo...
i = 15 = , sun.reflect.NativeMethodAccessorImpl@7291c18f
i = 16, foo...
i = 16 = , sun.reflect.GeneratedMethodAccessor1@6e8cf4c6
可以看到,15次之前都是使用的JDK反射执行,16次时,生成了一个代理类执行反射方法。 使用arthas工具查看该代理类,jad sun.reflect.GeneratedMethodAccessor1
。 可以看到如下:JDK在15次之后生成一个代理类,直接调用该方法,不使用反射,提高效率 。
源码如下:
Cglib代理原理
Cglib代理类是目标类的子类 。 所以目标类是final的不能代理,方法是final的代理会失效 。创建一个目标类
public class Target {
public void save ( ) {
System . out. println ( "save" ) ;
}
public void save ( int i) {
System . out. println ( "save i = " + i) ;
}
}
创建一个代理类
public class Proxy extends Target {
static Method save0;
static Method save1;
static {
try {
save0 = Target . class . getMethod ( "save" ) ;
save1 = Target . class . getMethod ( "save" , int . class ) ;
} catch ( NoSuchMethodException e) {
throw new NoSuchMethodError ( e. getMessage ( ) ) ;
}
}
private MethodInterceptor methodInterceptor;
public void setMethodInterceptor ( MethodInterceptor methodInterceptor) {
this . methodInterceptor = methodInterceptor;
}
@Override
public void save ( ) {
try {
methodInterceptor. intercept ( this , save0, new Object [ 0 ] , null ) ;
} catch ( Throwable e) {
throw new UndeclaredThrowableException ( e) ;
}
}
@Override
public void save ( int i) {
try {
methodInterceptor. intercept ( this , save1, new Object [ ] { i} , null ) ;
} catch ( Throwable e) {
throw new UndeclaredThrowableException ( e) ;
}
}
}
测试类:
public class TestProxy {
public static void main ( String [ ] args) {
Proxy proxy = new Proxy ( ) ;
Target target = new Target ( ) ;
proxy. setMethodInterceptor ( new MethodInterceptor ( ) {
@Override
public Object intercept ( Object o, Method method, Object [ ] args, MethodProxy methodProxy) throws Throwable {
System . out. println ( "before..." ) ;
return method. invoke ( target, args) ;
}
} ) ;
proxy. save ( ) ;
proxy. save ( 10 ) ;
}
}
在Cglib中,也有对JDK反射的优化,就是MethodProxy
类。 生成MethodProxy
类。
public class Proxy extends Target {
static Method save0;
static Method save1;
static MethodProxy methodProxy0;
static MethodProxy methodProxy1;
static {
try {
save0 = Target . class . getMethod ( "save" ) ;
save1 = Target . class . getMethod ( "save" , int . class ) ;
methodProxy0 = MethodProxy . create ( Target . class , Proxy . class , "()V" , "save" , "saveSuper" ) ;
methodProxy1 = MethodProxy . create ( Target . class , Proxy . class , "(I)V" , "save" , "saveSuper" ) ;
} catch ( NoSuchMethodException e) {
throw new NoSuchMethodError ( e. getMessage ( ) ) ;
}
}
private MethodInterceptor methodInterceptor;
public void setMethodInterceptor ( MethodInterceptor methodInterceptor) {
this . methodInterceptor = methodInterceptor;
}
public void saveSuper ( ) {
super . save ( ) ;
}
public void saveSuper ( int i) {
super . save ( i) ;
}
@Override
public void save ( ) {
try {
methodInterceptor. intercept ( this , save0, new Object [ 0 ] , methodProxy0) ;
} catch ( Throwable e) {
throw new UndeclaredThrowableException ( e) ;
}
}
@Override
public void save ( int i) {
try {
methodInterceptor. intercept ( this , save1, new Object [ ] { i} , methodProxy1) ;
} catch ( Throwable e) {
throw new UndeclaredThrowableException ( e) ;
}
}
}
不使用反射调用
public class TestProxy {
public static void main ( String [ ] args) {
Proxy proxy = new Proxy ( ) ;
Target target = new Target ( ) ;
proxy. setMethodInterceptor ( new MethodInterceptor ( ) {
@Override
public Object intercept ( Object p, Method method, Object [ ] args, MethodProxy methodProxy) throws Throwable {
System . out. println ( "before..." ) ;
Object invoke = methodProxy. invokeSuper ( p, args) ;
return invoke;
}
} ) ;
proxy. save ( ) ;
proxy. save ( 10 ) ;
}
}
MethodProxy原理
JDK反射的性能不好,Cglib使用MethodProxy类的两个方法,代替了反射。
Object invoke = methodProxy. invoke ( target, args) ;
Object invoke = methodProxy. invokeSuper ( p, args) ;
Cglib底层是如何实现不通过反射调用的?为这两个方法分别生成了两个代理类 ,代替反射。 这两个代理类都继承自FastClass
类(抽象类)。
模拟传入目标类的方法使用的代理类。
public class TargetFastClass {
static Signature s0 = new Signature ( "save" , "()V" ) ;
static Signature s1 = new Signature ( "save" , "(I)V" ) ;
public int getIndex ( Signature signature) {
if ( s0. equals ( signature) ) {
return 0 ;
} else if ( s1. equals ( signature) ) {
return 1 ;
}
return - 1 ;
}
public Object invoke ( int index, Object target, Object [ ] args) {
if ( index == 0 ) {
( ( Target ) target) . save ( ) ;
return null ;
} else if ( index == 1 ) {
( ( Target ) target) . save ( ( int ) args[ 0 ] ) ;
return null ;
} else {
throw new RuntimeException ( "未找到方法" ) ;
}
}
}
模拟传入代理的方法执行。
public class ProxyFastClass {
static Signature s0 = new Signature ( "saveSuper" , "()V" ) ;
static Signature s1 = new Signature ( "saveSuper" , "(I)V" ) ;
public int getIndex ( Signature signature) {
if ( s0. equals ( signature) ) {
return 0 ;
} else if ( s1. equals ( signature) ) {
return 1 ;
}
return - 1 ;
}
public Object invoke ( int index, Object proxy, Object [ ] args) {
if ( index == 0 ) {
( ( Proxy ) proxy) . saveSuper ( ) ;
return null ;
} else if ( index == 1 ) {
( ( Proxy ) proxy) . saveSuper ( ( int ) args[ 0 ] ) ;
return null ;
} else {
throw new RuntimeException ( "未找到方法" ) ;
}
}
}
在执行这两个方法时,会创建FastClass的两个代理类,执行本身的方法,避免反射。
Object invoke = methodProxy. invoke ( target, args) ;
Object invoke = methodProxy. invokeSuper ( p, args) ;
Spring代理选择
public class MyAdvisor {
public static void main ( String [ ] args) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( "execution(* foo())" ) ;
MethodInterceptor advice = new MethodInterceptor ( ) {
@Override
public Object invoke ( MethodInvocation invocation) throws Throwable {
System . out. println ( "before" ) ;
Object res = invocation. proceed ( ) ;
System . out. println ( "after" ) ;
return res;
}
} ;
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor ( pointcut, advice) ;
ProxyFactory proxyFactory = new ProxyFactory ( ) ;
Target target = new Target ( ) ;
proxyFactory. setTarget ( target) ;
proxyFactory. setInterfaces ( target. getClass ( ) . getInterfaces ( ) ) ;
proxyFactory. setProxyTargetClass ( true ) ;
proxyFactory. addAdvisor ( advisor) ;
I1 proxy = ( I1) proxyFactory. getProxy ( ) ;
System . out. println ( proxy. getClass ( ) ) ;
proxy. foo ( ) ;
proxy. bar ( ) ;
}
interface I1 {
void foo ( ) ;
void bar ( ) ;
}
static class Target implements I1 {
@Override
public void foo ( ) {
System . out. println ( "foo()..." ) ;
}
@Override
public void bar ( ) {
System . out. println ( "bar()..." ) ;
}
}
}
切点匹配和@Transcation解析
匹配切点底层都实现了MethodMatcher接口,用来执行方法的匹配。
public class PointcutTest {
public static void main ( String [ ] args) throws NoSuchMethodException {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( "execution(* bar())" ) ;
System . out. println ( pointcut. matches ( T1. class . getMethod ( "foo" ) , T1. class ) ) ;
System . out. println ( pointcut. matches ( T1. class . getMethod ( "bar" ) , T1. class ) ) ;
AspectJExpressionPointcut pointcut2 = new AspectJExpressionPointcut ( ) ;
pointcut2. setExpression ( "@annotation(org.springframework.transaction.annotation.Transactional)" ) ;
System . out. println ( pointcut2. matches ( T1. class . getMethod ( "foo" ) , T1. class ) ) ;
System . out. println ( pointcut2. matches ( T1. class . getMethod ( "bar" ) , T1. class ) ) ;
StaticMethodMatcherPointcut pointcut3 = new StaticMethodMatcherPointcut ( ) {
@Override
public boolean matches ( Method method, Class < ? > targetClass) {
MergedAnnotations annotations = MergedAnnotations . from ( method) ;
if ( annotations. isPresent ( Transactional . class ) ) {
return true ;
}
annotations = MergedAnnotations . from ( targetClass, MergedAnnotations. SearchStrategy . TYPE_HIERARCHY) ;
if ( annotations. isPresent ( Transactional . class ) ) {
return true ;
}
return false ;
}
} ;
System . out. println ( "-------------------" ) ;
System . out. println ( pointcut3. matches ( T2. class . getMethod ( "foo" ) , T2. class ) ) ;
System . out. println ( pointcut3. matches ( T3. class . getMethod ( "foo" ) , T3. class ) ) ;
}
static class T1 {
@Transactional
public void foo ( ) { } ;
public void bar ( ) { } ;
}
@Transactional
static class T2 {
public void foo ( ) { } ;
}
@Transactional
interface I1 {
}
static class T3 implements I1{
public void foo ( ) { } ;
}
}
Advisor和Aspect的解析过程
public class MyAdvisorAndAspect {
public static void main ( String [ ] args) throws NoSuchMethodException , InvocationTargetException , IllegalAccessException {
GenericApplicationContext applicationContext = new GenericApplicationContext ( ) ;
applicationContext. registerBean ( "aspect1" , Aspect1 . class ) ;
applicationContext. registerBean ( "config" , Config . class ) ;
applicationContext. registerBean ( ConfigurationClassPostProcessor . class ) ;
applicationContext. registerBean ( AnnotationAwareAspectJAutoProxyCreator . class ) ;
applicationContext. refresh ( ) ;
AnnotationAwareAspectJAutoProxyCreator creator = applicationContext. getBean ( AnnotationAwareAspectJAutoProxyCreator . class ) ;
Class < ? extends AnnotationAwareAspectJAutoProxyCreator > aClass = creator. getClass ( ) ;
Class < ? > superclass = aClass. getSuperclass ( ) ;
Class < ? > superclass1 = superclass. getSuperclass ( ) ;
Method findCandidateAdvisors = superclass1. getDeclaredMethod ( "findEligibleAdvisors" , Class . class , String . class ) ;
findCandidateAdvisors. setAccessible ( true ) ;
System . out. println ( findCandidateAdvisors) ;
List < Advisor > advisorList = ( List < Advisor > ) findCandidateAdvisors. invoke ( creator, Target1 . class , "target1" ) ;
for ( Advisor advisor : advisorList) {
System . out. println ( advisor) ;
}
Class < ? > superclass2 = superclass1. getSuperclass ( ) ;
Method wrapIfNecessary = superclass2. getDeclaredMethod ( "wrapIfNecessary" , Object . class , String . class , Object . class ) ;
wrapIfNecessary. setAccessible ( true ) ;
Object target1 = wrapIfNecessary. invoke ( creator, new Target1 ( ) , "target1" , "target1" ) ;
Object target2 = wrapIfNecessary. invoke ( creator, new Target2 ( ) , "target1" , "target1" ) ;
System . out. println ( target1. getClass ( ) ) ;
System . out. println ( target2. getClass ( ) ) ;
( ( Target1 ) target1) . foo ( ) ;
}
static class Target1 {
public void foo ( ) {
System . out. println ( "target1 foo" ) ;
}
}
static class Target2 {
public void bar ( ) {
System . out. println ( "target2 bar" ) ;
}
}
@Aspect
static class Aspect1 {
@Before ( "execution(* foo())" )
public void before ( ) {
System . out. println ( "aspect1 before" ) ;
}
@After ( "execution(* foo())" )
public void after ( ) {
System . out. println ( "aspect1 after" ) ;
}
}
@Configuration
static class Config {
@Bean
public Advisor advisor3 ( MethodInterceptor advice3) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( "execution(* foo())" ) ;
return new DefaultPointcutAdvisor ( pointcut, advice3) ;
}
@Bean
public MethodInterceptor advice3 ( ) {
return new MethodInterceptor ( ) {
@Override
public Object invoke ( MethodInvocation invocation) throws Throwable {
System . out. println ( "advice3 before" ) ;
Object proceed = invocation. proceed ( ) ;
System . out. println ( "advice3 after" ) ;
return proceed;
}
} ;
}
}
}
代理的创建时机
在初始化之后创建代理对象。(无循环依赖的时候) 在依赖注入之前创建代理对象。(有循环依赖的时候)
public class ProxyCreateTime {
public static void main ( String [ ] args) {
GenericApplicationContext applicationContext = new GenericApplicationContext ( ) ;
applicationContext. registerBean ( ConfigurationClassPostProcessor . class ) ;
applicationContext. registerBean ( Config . class ) ;
applicationContext. refresh ( ) ;
applicationContext. close ( ) ;
}
@Configuration
static class Config {
@Bean
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator ( ) {
return new AnnotationAwareAspectJAutoProxyCreator ( ) ;
}
@Bean
public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor ( ) {
return new AutowiredAnnotationBeanPostProcessor ( ) ;
}
@Bean
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 new MethodInterceptor ( ) {
@Override
public Object invoke ( MethodInvocation invocation) throws Throwable {
System . out. println ( "before..." ) ;
return invocation. proceed ( ) ;
}
} ;
}
@Bean
public Target1 target1 ( ) {
return new Target1 ( ) ;
}
@Bean
public Target2 target2 ( ) {
return new Target2 ( ) ;
}
}
static class Target1 {
public Target1 ( ) {
System . out. println ( "target1 construct" ) ;
}
public void foo ( ) {
System . out. println ( "foo..." ) ;
}
@PostConstruct
public void init ( ) {
System . out. println ( "target1 init..." ) ;
}
}
static class Target2 {
public Target2 ( ) {
System . out. println ( "target2 construct" ) ;
}
@Autowired
public void setTarget1 ( Target1 target1) {
System . out. println ( target1. getClass ( ) ) ;
}
@PostConstruct
public void init ( ) {
System . out. println ( "target2 init..." ) ;
}
}
}
高级切面转低级切面
开发的时候一般使用高级切面Aspect,Spring底层会转化为低级切面。
public class Aspect2Advisor {
static class Aspect {
@Before ( "execution(* foo())" )
public void before1 ( ) {
System . out. println ( "before1" ) ;
}
@After ( "execution(* foo())" )
public void After ( ) {
System . out. println ( "After" ) ;
}
}
public static void main ( String [ ] args) {
AspectInstanceFactory factory = new SimpleAspectInstanceFactory ( Aspect . class ) ;
for ( Method declaredMethod : Aspect . class . getDeclaredMethods ( ) ) {
if ( declaredMethod. isAnnotationPresent ( Before . class ) ) {
Before before = declaredMethod. getAnnotation ( Before . class ) ;
String execution = before. value ( ) ;
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( execution) ;
AspectJMethodBeforeAdvice advice = new AspectJMethodBeforeAdvice ( declaredMethod, pointcut, factory) ;
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor ( pointcut, advice) ;
System . out. println ( advisor) ;
}
if ( declaredMethod. isAnnotationPresent ( After . class ) ) {
After after = declaredMethod. getAnnotation ( After . class ) ;
String execution = after. value ( ) ;
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( execution) ;
AspectJAfterAdvice advice = new AspectJAfterAdvice ( declaredMethod, pointcut, factory) ;
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor ( pointcut, advice) ;
System . out. println ( advisor) ;
}
}
}
}
所有切面转化为环绕通知后调用链执行
public class Aspect2Advisor {
static class Aspect {
@Before ( "execution(* foo())" )
public void before1 ( ) {
System . out. println ( "before1" ) ;
}
@After ( "execution(* foo())" )
public void after ( ) {
System . out. println ( "After" ) ;
}
@AfterReturning ( "execution(* foo())" )
public void afterReturning ( ) {
System . out. println ( "afterReturning" ) ;
}
@Around ( "execution(* foo())" )
public Object around ( ProceedingJoinPoint joinPoint) throws Throwable {
System . out. println ( "around before" ) ;
Object proceed = joinPoint. proceed ( ) ;
System . out. println ( "around after" ) ;
return proceed;
}
}
static class Target {
public void foo ( ) {
System . out. println ( "foo..." ) ;
}
}
public static void main ( String [ ] args) throws Throwable {
AspectInstanceFactory factory = new SimpleAspectInstanceFactory ( Aspect . class ) ;
List < Advisor > list = new ArrayList < > ( ) ;
for ( Method declaredMethod : Aspect . class . getDeclaredMethods ( ) ) {
if ( declaredMethod. isAnnotationPresent ( Before . class ) ) {
Before before = declaredMethod. getAnnotation ( Before . class ) ;
String execution = before. value ( ) ;
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( execution) ;
AspectJMethodBeforeAdvice advice = new AspectJMethodBeforeAdvice ( declaredMethod, pointcut, factory) ;
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor ( pointcut, advice) ;
list. add ( advisor) ;
} else if ( declaredMethod. isAnnotationPresent ( After . class ) ) {
After after = declaredMethod. getAnnotation ( After . class ) ;
String execution = after. value ( ) ;
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( execution) ;
AspectJAfterAdvice advice = new AspectJAfterAdvice ( declaredMethod, pointcut, factory) ;
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor ( pointcut, advice) ;
list. add ( advisor) ;
} else if ( declaredMethod. isAnnotationPresent ( AfterReturning . class ) ) {
AfterReturning after = declaredMethod. getAnnotation ( AfterReturning . class ) ;
String execution = after. value ( ) ;
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( execution) ;
AspectJAfterReturningAdvice advice = new AspectJAfterReturningAdvice ( declaredMethod, pointcut, factory) ;
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor ( pointcut, advice) ;
list. add ( advisor) ;
} else if ( declaredMethod. isAnnotationPresent ( Around . class ) ) {
Around after = declaredMethod. getAnnotation ( Around . class ) ;
String execution = after. value ( ) ;
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( execution) ;
AspectJAroundAdvice advice = new AspectJAroundAdvice ( declaredMethod, pointcut, factory) ;
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor ( pointcut, advice) ;
list. add ( advisor) ;
}
}
for ( Advisor advisor : list) {
System . out. println ( advisor) ;
}
Target target = new Target ( ) ;
ProxyFactory proxyFactory = new ProxyFactory ( ) ;
proxyFactory. setTarget ( target) ;
proxyFactory. addAdvice ( ExposeInvocationInterceptor . INSTANCE) ;
proxyFactory. addAdvisors ( list) ;
System . out. println ( ">>>>>>>>>>>>>" ) ;
List < Object > methodInterceptorList = proxyFactory. getInterceptorsAndDynamicInterceptionAdvice ( Target . class . getMethod ( "foo" ) , Target . class ) ;
for ( Object o : methodInterceptorList) {
System . out. println ( o) ;
}
System . out. println ( ">>>>>>>>>>>>>>>>>>>>>" ) ;
Constructor < ReflectiveMethodInvocation > constructor = ReflectiveMethodInvocation . class . getDeclaredConstructor ( Object . class , Object . class , Method . class , Object [ ] . class , Class . class , List . class ) ;
constructor. setAccessible ( true ) ;
MethodInvocation methodInvocation = constructor. newInstance ( null , target, Target . class . getMethod ( "foo" ) , new Object [ 0 ] , Target . class , methodInterceptorList) ;
methodInvocation. proceed ( ) ;
}
}
自定义执行环绕通知的责任链
public class MyChain {
public static void main ( String [ ] args) throws Throwable {
Target target = new Target ( ) ;
ArrayList < MethodInterceptor > list = new ArrayList < > ( ) ;
list. add ( new Advice1 ( ) ) ;
list. add ( new Advice2 ( ) ) ;
MyInvocation invocation = new MyInvocation ( target, Target . class . getMethod ( "foo" ) , args, list) ;
invocation. proceed ( ) ;
}
static class Target {
public void foo ( ) {
System . out. println ( "foo..." ) ;
}
}
static class Advice1 implements MethodInterceptor {
@Override
public Object invoke ( MethodInvocation invocation) throws Throwable {
System . out. println ( "advice1 before" ) ;
Object proceed = invocation. proceed ( ) ;
System . out. println ( "advice1 after" ) ;
return proceed;
}
}
static class Advice2 implements MethodInterceptor {
@Override
public Object invoke ( MethodInvocation invocation) throws Throwable {
System . out. println ( "advice2 before" ) ;
Object proceed = invocation. proceed ( ) ;
System . out. println ( "advice2 after" ) ;
return proceed;
}
}
static class MyInvocation implements MethodInvocation {
private Object target;
private Method method;
private Object [ ] args;
private List < MethodInterceptor > methodInterceptorList;
private int count = 1 ;
public MyInvocation ( Object target, Method method, Object [ ] args, List < MethodInterceptor > methodInterceptor) {
this . target = target;
this . method = method;
this . args = args;
this . methodInterceptorList = methodInterceptor;
}
@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) ;
}
MethodInterceptor interceptor = methodInterceptorList. get ( count++ - 1 ) ;
return interceptor. invoke ( this ) ;
}
@Override
public Object getThis ( ) {
return target;
}
@Override
public AccessibleObject getStaticPart ( ) {
return method;
}
}
}