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 {
@Override
public int foo() {
System.out.println("foo");
return 100;
}
@Override
public void bar() {
System.out.println("bar");
}
}
public static void main(String[] args) {
$Proxy0 proxy0 = new $Proxy0(new InvocationHandler() {
@Override
public 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;
}
@Override
public int foo() {
try {
return (int) h.invoke(this, foo, new Object[0]) + 1;
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable e) {
//对于检查异常需要包装成RuntimeException
throw new UndeclaredThrowableException(e);
}
}
@Override
public void bar() {
try {
h.invoke(this, bar, new Object[0]);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable e) {
//对于检查异常需要包装成RuntimeException
throw 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 volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
- 可以看到
JDK
反射的底层是使用了MethodAccessor
的实现类 - 实际上由于反射的效率低下,在循环反射16次后,直到第17次会使用
GeneratedMethodAccessor
创建一个代理对象出来直接调用方法,不再使用反射调用