静态代理
此处就不累述了,就是简单的引用被代理对象,在调用方法前后hook。
缺点
- 随着需求的增加和变动,容易导致proxy的膨胀。
- 目标对象一定要实现接口。
jdk动态代理
原理同静态代理。只是proxy类是动态生成的,不用用户亲自写代码。Proxy类引用了被代理类,并实现了委托接口,调用接口通过反射方式并进行hook。
优点
- 适合频繁、反复地创建代理对象。
缺点
- 目标对象一定要实现接口
demo
public interface IFly {
String flying();
}
public class Bird implements IFly {
@Override
public String flying() {
LOGGER.info("flying");
return "flying";
}
}
public class ProxyFactory {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
LOGGER.info("invoke start");
Object obj = method.invoke(target, args);
LOGGER.info("invoke end");
return obj;
}
});
}
}
public class Main {
public static void main(String[] args) {
IFly f = new Bird();
IFly proxy = (IFly) new ProxyFactory(f).getProxyInstance();
proxy.flying();
}
}
cglib代理
运行时动态生成字节码(相当于生成了一个全新的被代理类,而不是通过引用的方式),调用方法时直接调用(FastMethod),而不是通过反射,提升了效率,但生成代理类的效率会比JDK动态代理慢。
demo
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
//Bird类同上
public class DynamicProxy implements MethodInterceptor {
Object target;
public Object getProxyObject(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(target.getClass());
return enhancer.create();
}
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
LOGGER.info("invoke start");
LOGGER.info(methodProxy.getSuperName());
Object result = methodProxy.invoke(target, args);
LOGGER.info("invoke end");
return result;
}
}
public class Main {
public static void main(String[] args) {
Bird bird = (Bird) new DynamicProxy().getProxyObject(new Bird());
bird.flying();
}
}
应用场景
切面编程AOP
其他
- JDK动态代理生成 代理对象class:System.setProperty(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);
- cglib 生成代理对象class:System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, “/users/mdm/Documents/workspace2/CG/”);
- 字节码查看工具:JD-GUI
- 反编译class工具:jad