JDK与CGLIB动态代理区别 && 使用示例

JDK与CGLIB动态代理区别:

JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

CGLIB动态代理是利用asm开源包,将代理对象类的class进来,通过修改其字节码文件生成子类来处理。

对于动态代理来说,Spring框架中的AOP使用最为经典:

  1. 如果目标对象实现了接口,默认情况下采用JDK的动态代理实现AOP
  2. 如果目标对象实现了接口,可以强制使用CGLIB实现AOP。只要在Spring配置文件中添加 <aop:aspectj-autoproxy proxy-target-class=“true”/>
  3. 如果目标对象没有实现接口,必须采用CGLIB方式,Spring会自动在JDK动态代理和CGLIB动态代理之间转换

注意事项:

  1. JDK动态代理只能对实现了接口的类生成代理
  2. CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,被代理类不要求实现接口。因为采用的继承的方式,所以被代理类中的方法不能用final修饰。

JDK动态代理实现示例:

创建被代理服务器类

public interface JDKService {

    void doService();
}
public class JDKServiceImpl implements JDKService {

    @Override
    public void doService() {
        System.out.println("do service...");
    }
}

创建代理类,并调用被代理服务类中的方法:

public class JDKProxy {

    /**
     * 创建代理对象
     *
     * @param target 被代理对象
     * @return 代理对象
     */
    public static Object newJDKProxy(final Object target) {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), // 代理接口
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("JDK动态代理,监听开始!");
                        Object result = method.invoke(target, args); // 方法调用
                        System.out.println("JDK动态代理,监听结束!");
                        return result;
                    }
                });
    }

    public static void main(String[] args) {
        JDKService jdkService = new JDKServiceImpl();
        JDKService service = (JDKService) newJDKProxy(jdkService);
        service.doService();
    }
}

CGLIB动态代理实现示例:

创建被代理服务类:

public class CGLIBService {

    public void doService() {
        System.out.println("doService...");
    }
}

创建代理类,并调用被代理服务类中的方法:

public class CGLIBProxy {

    /**
     * 创建代理对象
     *
     * @param target 被代理对象
     * @return 代理对象
     */
    public Object newCGLIBProxy(final Object target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass()); // 设置父类,因为Cglib是针对指定的类生成一个子类,所以需要指定父类
        enhancer.setCallback(new MethodInterceptor() { // 设置回调
            @Override
            public Object intercept(Object o, Method method, Object[] parameters, MethodProxy methodProxy) throws Throwable {
                System.out.println("Cglib动态代理,监听开始!");
                Object result = method.invoke(target, parameters); // 方法执行
                System.out.println("Cglib动态代理,监听结束!");
                return result;
            }
        });
        Object result = enhancer.create(); // 创建并返回代理对象
        return result;
    }

    public static void main(String[] args) {
        CGLIBProxy cglib = new CGLIBProxy(); // 实例化CglibProxy对象
        CGLIBService service = (CGLIBService) cglib.newCGLIBProxy(new CGLIBService()); // 获取代理对象
        service.doService();
    }
}
上一篇:死磕Spring之AOP篇 - 初识JDK、CGLIB两种动态代理


下一篇:利用cglib的BeanCopier用原型模式以及享元模式完成对象的拷贝