动态代理
功能(方法)增强
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);
}
}