跳到主要内容

Java 中的代理实现方式

当一个对象不适合或者不能被其他对象直接引用时,可以给该对象生成一个代理对象,代理对象具有被代理对象的所有功能,这样其他对象使用代理对象时一样可以达到自己的需求

静态代理

  • 使用时需要定义接口或者父类,被代理对象和代理对象一起实现相同的接口或者继承相同的父类。缺点是必须为每个被代理对象生成一个代理对象

动态代理

  • 特点
    不需要实现接口,代理对象的实现是利用 JDK 的 API,动态的在内存中构建代理对象(需要指定创建代理对象/目标对象实现的接口类型)

JDK 实现

  • 特点

    1. 面向接口的动态代理(被代理对象必须要实现一个接口)
    2. 没有接口不可能
    3. 只能读取到接口上的一些注解
  • 代码

    // 代理工厂类  
    public class DynamicProxyFactory_java {
    private Object object;//被代理对象
    public DynamicProxyFactory_java(Object object) {
    this.object = object;
    }

    public Object getProxyInstance() {
    return Proxy.newProxyInstance(
    object.getClass().getClassLoader(),
    object.getClass().getInterfaces(),//所以这种模式必须实现接口
    new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("执行前准备...");
    Object invoke = method.invoke(object, args);//执行被代理对象的方法
    System.out.println("执行后处理...");
    return invoke;
    }
    }
    );
    }
    }
    // 在代理工厂的构造方法中传入需要被代理的对象,再通过调用 getProxyInstance() 方法即可获取代理对象
    public class Run {
    public static void main(String[] args) {
    BaseDao baseDao = new UserDao();
    BaseDao userDao = (BaseDao) new DynamicProxyFactory_java(baseDao).getProxyInstance();
    userDao.add();
    System.out.println("代理前对象:" + baseDao.getClass().getName());
    System.out.println("代理后对象:" + userDao.getClass().getName());
    }
    }

CGLIB 实现

  • CGLIB 动态代理不是 JDK 自带的方式,需要引入第三方 jar 包(cglib-xx.xx.x.jar)

  • 特点

    1. 面向父类的动态代理,也叫子类代理,通过在内存中构建一个子类对象实现对目标对象功能的扩展
    2. 有没有接口都可以使用
    3. 可以读取类上的注解
  • 代码

    // 动态代理工厂  
    public class DynamicProxyFactory_cglib implements MethodInterceptor {
    private Object object;//被代理对象
    public DynamicProxyFactory_cglib(Object object) {
    this.object = object;
    }
    /**
    * 创建代理对象
    */
    public Object getProxyInstance() {
    //工具类
    Enhancer enhancer = new Enhancer();
    //设置父类
    enhancer.setSuperclass(object.getClass());
    //设置回调函数
    enhancer.setCallback(this);
    //创建对象并返回
    return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    System.out.println("执行前准备...");
    Object invoke = method.invoke(object, args);
    System.out.println("执行后处理...");
    return invoke;
    }
    }

    // 被代理对象,没有实现任何接口
    public class MenuDao {
    public void add() {
    System.out.println("add Menu");
    }
    }
    // 使用方式
    public class Run {
    public static void main(String[] args) {
    MenuDao dao = new MenuDao();
    MenuDao menuDao = (MenuDao) new DynamicProxyFactory_cglib(dao).getProxyInstance();
    System.out.println("代理前对象:" + dao.getClass().getName());
    System.out.println("代理后对象:" + menuDao.getClass().getName());
    menuDao.add();
    }
    }

Spring AOP 中的实现方式

  • 关注 targetClass.isInterface(),判断这个类是不是接口,如果是接口使用 JDK 动态代理进行实现,否则使用 CGLIB 动态代理实现
    public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    Class<?> targetClass = config.getTargetClass();
    if (targetClass == null) {
    throw new AopConfigException("TargetSource cannot determine target class: " +
    "Either an interface or a target is required for proxy creation.");
    }
    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    return new JdkDynamicAopProxy(config);
    }
    return new ObjenesisCglibAopProxy(config);
    }
    else {
    return new JdkDynamicAopProxy(config);
    }
    }
    }