动态代理

2022/4/2 23:21:46

本文主要是介绍动态代理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

功能(方法)增强

1.继承:通过继承父类,对父类中需要增强的方法进行重写,达到增强方法的效果

​ 必须条件:必须要知道继承谁?通过我们只能拿到对象,对象是接口类型,我们不知道类具体是啥

2.装饰者模式:23种设计模式之一

​ 核心思想:“皇亲国戚携天子令诸侯”---》“挟持被增强的对象,让他来帮我们做事情,我们只需要对他增强”
​ 必须条件:必须实现与被增强的对象相同的接口,必须实现接口中的所有方法。接口中如果有100个方法,
​ 我只想对其中1个进行增强,但我也必须实现另外99个方法。
​ 步骤:1.编写装饰者类 MyHashMap 实现 被增强的对象相同的接口
​ 2.提供有参构造,构造中传入被增强的对象
​ 3.挟持对象,让他帮我们干事情,我只需要负责增强的部分就可以了。

//装饰类
public class MyHashMap implements Map<String,String> {

    private Map<String,String> map;//挟持一个正真map

    public MyHashMap(Map<String, String> map) {
        this.map = map;
    }

    //增强了put功能
    @Override
    public String put(String key, String value) {
        String oldValue = map.put(key, value);
        if(oldValue==null){
            System.out.println("保存成功");
        }else{
            System.out.println("保存成功,被覆盖的旧值为:"+oldValue);
        }
        return oldValue;
    }



    @Override
    public int size() {
        return map.size();
    }

    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return map.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return map.containsValue(value);
    }

    @Override
    public String get(Object key) {
        return map.get(key);
    }



    @Override
    public String remove(Object key) {
        return map.remove(key);
    }

    @Override
    public void putAll(Map<? extends String, ? extends String> m) {
        map.putAll( m);
    }

    @Override
    public void clear() {
        map.clear();
    }

    @Override
    public Set<String> keySet() {
        return map.keySet();
    }

    @Override
    public Collection<String> values() {
        return map.values();
    }

    @Override
    public Set<Entry<String, String>> entrySet() {
        return map.entrySet();
    }
}

3.动态代理模式:23种设计模式之一

​ 核心思想:内存种创建一个代理类,实现被增强的对象相同的接口,与被增强的对象是兄弟关系
​ 必须条件:被增强的对象,必须实现接口。
​ 步骤:1.代理对象 = Proxy.newProxyInstance(类加载器,被增强的对象实现的所有接口,InvocationHandler接口的实现类对象)
​ 2.代理对象调用任何方法都在执行InvocationHandler里面invoke方法

public class Demo3 {
    public static void main(String[] args) throws ClassNotFoundException {
        Map<String, String> map = new HashMap<>();
        /*
            使用动态代理对map进行增强,增强他的put方法
         */
        //就是在内存中,生成一个代理类,并且返回该类的对象。
        /*
            三个参数:1. 类加载器
                        内存中生成了代理类加载到jvm中
                    2. 被增强对象所有实现的所有接口:内存种创建一个代理类,实现被增强的对象相同的接口
                    3. InvocationHandler接口的实现类对象:如何增强。
         */
        
        //map对象实现的所有接口,返回的是接口class数组
        //Class<?>[] arr = [Map.class,Serializable.class,Cloneable.class]
       /* Class<Demo1> cls = Demo1.class;
        Class cls2 = Class.forName("com.itheima.demo1.Student");
        Class cls4 = Map.class;
        Class[] arr5 = {cls,cls2,cls4};*/
        //拿到hashmap实现的接口数组
        Class<?>[] arr = map.getClass().getInterfaces();
        
        Map<String,String> mapProxy = (Map<String, String>) Proxy.newProxyInstance(Demo3.class.getClassLoader(), arr, (proxy, method, args1) -> {
            //proxy 代理对象本身(没有用,忽略)
            //method 代理对象正在调用什么方法,method就是该方法的方法对象
            //args  代理对象正在调用方法传入什么参数,args就是什么。["张三","123"]
            if(method.getName().equals("put")){
                String oldVlaue = (String) method.invoke(map, args1);
                if(oldVlaue==null){
                    System.out.println("保存成功");
                }else{
                    System.out.println("保存成功,覆盖的旧值为:"+oldVlaue);
                }
                return oldVlaue;
            }
            return method.invoke(map, args1);//让真正的map去调用
        });
        
        
        //mapProxy:牛逼的代理对象
        mapProxy.put("张三","123");//保存成功
        mapProxy.put("李四","222");//保存成功
        mapProxy.put("张三","444");//保存成功,覆盖的旧值为:123

        for (String s : mapProxy.keySet()) {
            System.out.println(s+" " +mapProxy.get(s));
        }
        System.out.println(mapProxy);

    }
}


这篇关于动态代理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程