Spring底层原理(六)
本章内容
介绍AOP的实现方式、JDK代理的模拟实现与源码
AOP的实现方式
-
使用代理模式
- jdk动态代理
- cglib动态代理
-
使用aspectj的编译器,该编译器会直接对字节码进行修改,可以实现静态方法增强
-
使用
javaagent
,在jvm option中指定-javaagent:aspectjweaver.jar
,它会在字节码加载阶段对方法进行织入
JDK动态代理的模拟实现
public interface InvocationHandler {/*** @param proxy 代理对象* @param method 调用的方法* @param args 方法参数* @return 返回结果* @throws Throwable 运行异常*/Object invoke(Object proxy, Method method,Object[] args) throws Throwable;
}public interface Foo {int foo();void bar();
}
public class Obj {static class Target implements Foo {@Overridepublic int foo() {System.out.println("foo");return 100;}@Overridepublic void bar() {System.out.println("bar");}}public static void main(String[] args) {$Proxy0 proxy0 = new $Proxy0(new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Exception {System.out.println("before...");return method.invoke(new Target(),args);}});proxy0.bar();int foo = proxy0.foo();System.out.println(foo);}
}
public class $Proxy0 implements Foo {private InvocationHandler h;static Method foo;static Method bar;static {try {bar = Foo.class.getDeclaredMethod("bar");foo = Foo.class.getDeclaredMethod("foo");} catch (NoSuchMethodException e) {e.printStackTrace();}}public $Proxy0(InvocationHandler h) {this.h = h;}@Overridepublic int foo() {try {return (int) h.invoke(this, foo, new Object[0]) + 1;} catch (RuntimeException | Error e) {throw e;} catch (Throwable e) {//对于检查异常需要包装成RuntimeExceptionthrow new UndeclaredThrowableException(e);}}@Overridepublic void bar() {try {h.invoke(this, bar, new Object[0]);} catch (RuntimeException | Error e) {throw e;} catch (Throwable e) {//对于检查异常需要包装成RuntimeExceptionthrow new UndeclaredThrowableException(e);}}
}
JDK动态代理源码
JDK动态代理的优化
public Object invoke(Object obj, Object... args)throws IllegalAccessException, IllegalArgumentException,InvocationTargetException{if (!override) {Class<?> caller = Reflection.getCallerClass();checkAccess(caller, clazz,Modifier.isStatic(modifiers) ? null : obj.getClass(),modifiers);}MethodAccessor ma = methodAccessor; // read volatileif (ma == null) {ma = acquireMethodAccessor();}return ma.invoke(obj, args);}
- 可以看到
JDK
反射的底层是使用了MethodAccessor
的实现类 - 实际上由于反射的效率低下,在循环反射16次后,直到第17次会使用
GeneratedMethodAccessor
创建一个代理对象出来直接调用方法,不再使用反射调用