必须条件:必须要知道继承谁?通过我们只能拿到对象,对象是接口类型,我们不知道类具体是啥
核心思想:“皇亲国戚携天子令诸侯”---》“挟持被增强的对象,让他来帮我们做事情,我们只需要对他增强”
必须条件:必须实现与被增强的对象相同的接口,必须实现接口中的所有方法。接口中如果有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(); } }
核心思想:内存种创建一个代理类,实现被增强的对象相同的接口,与被增强的对象是兄弟关系
必须条件:被增强的对象,必须实现接口。
步骤: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); } }