java延迟加载和动态代理小结

延迟加载的核心思想是:如果当前并没有使用这个组件,则不需要真正地初始化它,使用一个代理对象替代它的原有的位置,只要在真正需要的时候才对它进行加载。使用代理模式的延迟加载是非常有意义的,首先,它可以在时间轴上分散系统压力,尤其在系统启动时,不必完成所有的初始化工作,从而加速启动时间;其次,对很多真实主题而言,在软件启动直到被关闭的整个过程中,可能根本不会被调用,初始化这些数据无疑是一种资源浪费。例如使用代理类封装数据库查询类后,系统的启动过程这个例子。若系统不使用代理模式,则在启动时就要初始化 DBRequest对象,而使用代理模式后,启动时只需要初始化一个轻量级的对象 DBProxy。

下面通过实例简要说明,方便初步了解:

这里拿数据库请求为例:(IDBRequest接口,DBRequest真实类,DBProxy代理)

接口:

public interface IDBRequest {
    public String request();
}

真实类:

public class DBRequest implements IDBRequest{

    public DBRequest(){
        System.out.println("init real class!!");
        try {
            Thread.sleep(1000);
            //数据库连接操作等
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public String request() {
        
        return "do request";
    }

}
代理类(实现延迟加载)

public class DBProxy implements IDBRequest{

    private DBRequest real=null;
//    protected DBProxy(){
//        System.out.println("init proxy!!");
//    }
    @Override
    public String request() {
        if(real==null){
            real=new DBRequest();//延迟代理,真真在使用的时候初始化等
        }
       
        return real.request();
    }

}

测试类:

public class Test {

    public static void main(String[] args) {
        IDBRequest request=new DBProxy();//这里不是真实初始化
        request.request();//延迟加载,这里才是初始化
        //使用动态代理生成
    }
}

这里测试没有调用具体方法,不执行实例化对象这些操作,只有当调用方法时候才实例化对象,这就是使用代理来进行延迟加载的优点,多用于哪些初始化工作大或初始任务占用资源的情景。

2、动态代理

动态代理是指在运行时动态生成代理类。即,代理类的字节码将在运行时生成并载入当前代理的 ClassLoader。与静态处理类相比,动态类有诸多好处。首先,不需要为真实主题写一个形式上完全一样的封装类,假如主题接口中的方法很多,为每一个接口写一个代理方法也很麻烦。如果接口有变动,则真实主题和代理类都要修改,不利于系统维护;其次,使用一些动态代理的生成方法甚至可以在运行时制定代理类的执行逻辑,从而大大提升系统的灵活性。

动态代理实现由多种方式,比如cglib javaassist或jdk自带的

下面(jdk自带)继续上例子,接口和真实类就是上面的,动态代理类(DBRequestHandle)

public class DBRequestHandle implements InvocationHandler{

    Object tar=null;//定义主题接口
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result=null;
        result=method.invoke(tar, args);
        return result;
    }
    public Object bind(Object tar){
        this.tar=tar;
        return Proxy.newProxyInstance(tar.getClass().getClassLoader(), tar.getClass().getInterfaces(), this);
    }

}

实现InvocationHandler即可;主题传入object,bind方法完成对主题对象绑定,然后具体调用invoke,这样就完成动态代理;这样好处是当目标方法增大时,不需要重写多种方法,一切调用委托给动态代理完成,只需要使用方法时传入目标对象即可。

public class Test {

    public static void main(String[] args) {
        //IDBRequest request=new DBProxy();//这里不是真实初始化
        //request.request();//延迟加载,这里才是初始化
        
        //使用动态代理生成
        DBRequestHandle proxy=new DBRequestHandle();//init proxy
        IDBRequest handle=(IDBRequest)proxy.bind(new DBRequest());//绑定对象
        handle.request();
    }
}

看完代码,现在我来回答,动态代理的作用是什么:

    Proxy类的代码量被固定下来,不会因为业务的逐渐庞大而庞大;
    可以实现AOP编程,实际上静态代理也可以实现,总的来说,AOP可以算作是代理模式的一个典型应用;
    解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变。


  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值