Java中代理分为静态代理和动态代理,其中动态代理又有jdk动态代理和cglib动态代理。
区别如下
类型 | 原理 | 类的类型 | 生成效率 | 执行效率 |
---|---|---|---|---|
jdk动态代理 | 反射机制 | 类必须要实现一个接口 | 较cglib快 | 较cglib慢 |
cglib动态代理 | ASM框架,通过FastClass机制直接调用方法 | 可以是普通类 | 较jdk慢 | 较jdk快 |
一般的,框架中默认使用jdk动态代理,如果class类没有实现接口的时候,需要转为cglib动态代理。
cglib动态代理例子
这里还是使用之前的例子,张三生病了,来不了公司,委托老王帮他办理请假流程。
下载2个jar包并引入cglib和asm。
https://repo1.maven.org/maven2/cglib/cglib/3.3.0/cglib-3.3.0.jar
https://mvnrepository.com/artifact/org.ow2.asm/asm/9.4
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 办理请假,这里需要实现接口。
*/
class BizLeaveImpl implements BizLeave{
public void doLeave(String name){
System.out.println(name + "办理请假");
}
}
interface BizLeave{
public void doLeave(String name);
}
public class CglibTest{
public static void main(String[] args) {
BizLeaveImpl bizLeave = new BizLeaveImpl(); // 被代理的对象
// 创建代理对象(创建的代理对象可以放在容器中缓存,后续调用时获取即可)
BizLeaveImpl proxyObject = (BizLeaveImpl) new CGProxy().getProxyObject(bizLeave);
proxyObject.doLeave("张三");
}
public static class CGProxy implements MethodInterceptor{
private Object target; // 被代理对象
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
System.out.println("调用方法"+ arg1.getName());
Object result = proxy.invokeSuper(arg0, arg2);
return result;
}
public Object getProxyObject(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
// 设置父类
enhancer.setSuperclass(this.target.getClass());
// 设置回调(在调用父类方法时,回调 this.intercept())
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
}
}
输出结果:
调用方法doLeave
张三办理请假
张三办理请假
jdk动态代理例子
/**
* 办理请假,这里需要实现接口,否则报错。
*/
class BizLeaveImpl implements BizLeave{
public void doLeave(String name){
System.out.println(name + "办理请假");
}
}
interface BizLeave{
public void doLeave(String name);
}
public class Zhangsan{
public static void main(String[] args) {
// 获取代理对象
BizLeave bizLeave = (BizLeave) (new JdkProxy().newProxyInstance(new BizLeaveImpl()));
bizLeave.doLeave("张三");
}
public static class JdkProxy implements InvocationHandler {
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用方法"+method.getName());
Object result = method.invoke(target, args);
return result;
}
/**
* 获取代理对象
**/
private Object newProxyInstance(Object targetObject){
// 目标对象赋值
this.target = targetObject;
// 返回代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
}