什么是代理

代理故名思意暂时代替他人做一件事。如厂家需要代理商帮他们宣传并售卖产品,如图所示:

什么是代理

在Java中,代理是一种常用的设计模式,代理又分为动态代理和静态代理。

Java静态代理

静态代理是Java编译时生成,代理类和委托类在编译时就已经确定好。

我们来看一个具体的场景,张三生病了,来不了公司,委托老王帮他办理请假流程,这里为了程序的可读性和篇幅,去掉了Interface的定义。

/**
 * 办理请假
 */
class BizLeave{
    public void doLeave(String name){
        System.out.println(name + "办理请假");
    }
}
/**
 * 代理人老王
 */
class ProxyLaoWang{
    private BizLeave bizLeave;

    public ProxyLaoWang(BizLeave bizLeave) {
        this.bizLeave = bizLeave;
    }

    public void doLeave(String name){
        bizLeave.doLeave(name);
    }
}
/**
 * 张三
 */
public class Zhangsan {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        Zhangsan zs = new Zhangsan();
        zs.setName("张三");
        BizLeave bizLeave = new BizLeave();
        ProxyLaoWang laoWang = new ProxyLaoWang(bizLeave);//办理请假这个事就拜托老王了
        laoWang.doLeave(zs.getName());
    }
} 

测试一下

从上面的例子中来看是没问题的,但是,如果代理的对象多了,老王这个代理对象在程序上就会变得很臃肿,为了解决这一问题,Java出现了动态代理。

Java动态代理

动态代理是JVM在运行的过程中,通过反射的方法动态生成,所以不存在预先生成的字节码文件。

这里,我们为了将代码放到一个文件中执行,将动态代理类定义为内部 public static 类

 /**
 * 办理请假,这里需要实现接口,否则报错。
 */
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);
        }

    }
}

测试一下

这样一来张三不论是办理请假还是做一些其它的办公操作都可以使用JdkProxy 代理类来完成,不过由于动态代理是JVM运行时处理的,所以效率没有静态代理高。

Java动态代理和静态代理的区别

  • 生成时期:静态代理是Java编译时生成,动态代理是JVM运行时动态生成。
  • 执行效率:静态代理较动态代理效率更高。
  • 维护代价:静态代理较动态代理更难维护。

Java动态代理应用

Java动态代理分类

  • JDK动态代理
  • Cglib动态代理

Java动态实际应用

  • SpringAOP
  • MyBatis