动态代理
分类
AspectJ编译-静态编译-AspectJ编译编译器
JDK动态代理-接口
cglib动态代理-子类(对ASM的封装)
javassist动态代理-dubbo
JDK动态代理
public interface Subject {
String sayHello();
}
public class SubjectImpl implements Subject {
@Override
public String sayHello() {
System.out.println(" Hello World");
return "success";
}
}
//******
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public ProxyInvocationHandler(Object target) {
this.target = target;
}
//****** 最终还是用的反射调用
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用处理器 ");
return method.invoke(target, args);
}
}
public class ProxyTest {
public static void main(String[] args) {
Subject subject = new SubjectImpl();
//******
Subject proxy = (Subject) Proxy
.newProxyInstance(
subject.getClass().getClassLoader(),
subject.getClass().getInterfaces(),
new ProxyInvocationHandler(subject));
proxy.sayHello();
}
}
public final class $Proxy0 extends Proxy implements Singer {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
//******
public final void perform(String var1) throws {
try {
//****** ProxyInvocationHandler.invoke();
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("main.learn.proxy.Singer").getMethod("perform", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
一些应用
- mybatis mapper。
- spring aop。
反射
运行时调用类方法,获取类属性,注解等。
比new慢
10亿次慢1s。。
//forName 调用本地方法 上下文切换
Class testUserClass = Class.forName("RefleDemo.TestUser");
TestUser testUser = (TestUser) testUserClass.newInstance();
//遍历查找方法,找不到还会找父类
Method method = testUserClass.getMethod("sayHi");
int i = 0;
while(i<100000000){
++i;
//关闭检查提高效率 开启非public调用
method.setAccessible(true);
method.invoke(testUser);
}
网友评论