java代理模式的应用场景

        从开始java学习到从事java工作这么多时间以来,对代理模式的概念和现实已经了解的比较清楚了,但是一直不知道它的应用场景到底是什么样的,网上的资料无非就是对方法的增强或者增加日志操作什么的,我想这些操作我做个包装类,在这个类中做这些处理不是一样吗?

先说说概念:静态代理、动态代理、cglib

静态代理:实例和代理类都实现了同一个接口,不管传递什么实例进代理类中都能调用方法,不需要在每个新生成的实例中重复写某一个方法

Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
(1)  Interface InvocationHandler:该接口中仅定义了一个方法
public objectinvoke(Object obj, Methond method, Object[] args)在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。
(2)  Proxy:该类即为动态代理类
static ObjectnewProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类在接口中声明过的方法)

3   cglib也是动态代理,不同于proxy,它不需要基于接口进行代理

代理模式的优点:

1、代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度;

2、代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了保护目标对象的作用

3、还有一个我认为的优点、使用代理类我们就可以不用管委托类方法中的变动,或者我们只需要做少量的调整,比如如果委托类中的某个方法突然改成私有了,那个不使用代理类我们需要在每个此方法调用的地方都要把反射处理才能调用,使用代理之后 我们只需要在代理类中处理就可以了,当然这些操作可以使用包装类做,但是问题就在于我们不知道哪个方法会变成私有,不可能每个方法都写个包装类进行反射处理。

缺点:

1、由于在客户端和真实对象之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢;

2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

3、静态代理在委托类变多的情况时会显的非常臃肿,不方便阅读与使用

最近研究了一下应用场景,说说我的理解吧,如果不对请大家指出。

1:类中的方法批量处理

2:方法的区分处理

3:当我们想要隐藏某个类,或者这个类中的部分方法

4:扩展功能

1 ===> 假如一个类中的方法有100个,我们想要对这些方法都做日志处理。这个时候我们就可以使用代理,简化代码,不需要在每个方法调用的时候都做日志处理。

2====> 基于委托类中的这100个方法,其中有50个方法我想做日志处理,另外40个方法我想做执行时间输出,另10个我不想做处理的时候用代理也是挻好的

3====> 如果某个类我想隐藏,但是每些方法又想给其它人使用就可以使用代理。这些隐藏又如私有化构造,或者内部类等。

4====> 扩展功能也是常说的功能,对方法进行增强等操作,对不同的权限进行不同的增强......

 

下面介绍一下cglib中的实现,参考https://www.cnblogs.com/xrq730/p/6661692.html

public class DaoFilter implements CallbackFilter {

    @Override
    public int accept(Method method) {
        if ("select".equals(method.getName())) {
            return 0;                 //这里返回的数字对应的是callback中的代理位置
        }
        return 1;
    }
    
}
@Test
    public void testCglib() {
        DaoProxy daoProxy = new DaoProxy();
        DaoAnotherProxy daoAnotherProxy = new DaoAnotherProxy();   //两个不同的代理
        
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Dao.class);
        enhancer.setCallbacks(new Callback[]{daoProxy, daoAnotherProxy, NoOp.INSTANCE});//代理中的位置0,1,2
        enhancer.setCallbackFilter(new DaoFilter());
        
        Dao dao = (Dao)enhancer.create();
        dao.update();  //update对应filter中的1,所以会使用daoAnotherProxy代理
        dao.select();  //select对应filter中的0,所以会使用daoProxy代理
                       //如果有个方法不想做处理就可以让filter返回2,这个就是使用NoOp.INSTANCE不做处理
    }

通常构造方法中对委托类的调用也会走代理,cglib中可以设置对构造方法中方法调用不使用代理

@Test
    public void testCglib() {
        DaoProxy daoProxy = new DaoProxy();
        DaoAnotherProxy daoAnotherProxy = new DaoAnotherProxy();
        
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Dao.class);
        enhancer.setCallbacks(new Callback[]{daoProxy, daoAnotherProxy, NoOp.INSTANCE});
        enhancer.setCallbackFilter(new DaoFilter());
        enhancer.setInterceptDuringConstruction(false); //===>此处默认是true,设置false后,构造方法中方法的调用不走代理
        Dao dao = (Dao)enhancer.create();
        dao.update();
        dao.select();
    }    

此外还可以使用泛型,对不同的委托进行代理

public class CglibTest<T> {
    
    public  T aaa(T t) {
        return t;
    }
    
    public void testCglib(T o,Class c) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        DaoProxy daoProxy = new DaoProxy();
        
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(c);
//        enhancer.setCallbacks(new Callback[]{daoProxy,NoOp.INSTANCE});
        enhancer.setCallback(daoProxy);
        
        @SuppressWarnings("unchecked")
        T dao = (T)enhancer.create();
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
            method.invoke(dao);
        }
    }
    
    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Dao dao = new Dao();
        CglibTest<Dao> c = new CglibTest<>();
        c.testCglib(dao, dao.getClass());
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章