spring--动态代理以及静态代理
静态代理自己理解:
1.定义了一个公共的接口类
2.类1实现了这个类,并实现其中的方法
3.代理类,实现接口,将上面的类1对象拿过来,并且在第接口类方法的基础上,拓展了自己的方法
4.创建类1对象,创建代理类对象,将第类1的对象给代理类
5.代理类调用自己的方法就可以实现类1以及自己扩展的方法
接口:定义一个公共的方法
package com.kuang.demo1;
/**
* @author Administrator
* @description: TODO
* @date 2021/11/25 17:21
*/
public interface Rent {
//接口;抽象;租房
public void rent();
}
真实角色(第一个类)
package com.kuang.demo1;
/**
* @author Administrator
* @description: TODO
* @date 2021/11/25 17:23
*/
//房东
public class Host implements Rent {
public void rent() {
System.out.println("出租房屋");
}
}
代理类
package com.kuang.demo1;
public class Proxy implements Rent {
private Host host;
public Proxy(){};
//将房东对象拿过来使用
public Proxy(Host host) {
this.host = host;
}
public void rent() {
host.rent();
look();
write();
money();
}
public void look() {
System.out.println("看房");
}
public void write() {
System.out.println("签合同");
}
public void money() {
System.out.println("收费");
}
}
使用者
package com.kuang.demo1;
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy(host);
//去找中介租房
proxy.rent();
}
}
优点:
不需要改变原来的代码,就可以扩展方法,也可以集中管理
使真实角色的方法可以纯粹,不用去管公共的方法
缺点:
每增加一个真实角色,就要增加一个代理角色,而且代码量翻倍(解决办法:使用动态代理)
动态代理
动态代理的代理类是直接生成的,不是我们写好的
动态代理分为两大类:基于接口的动态代理;基于类的动态代理
基于几口:jdk动态代理
基于类:cglib
基于java字节码实现:javasis
需要了解两个类
invocationHandler:处理代理实例,返回处理结果
Proxy:动态生成代理实例
接口
public interface Rent { //接口:租房 public void rent(); }
真实角色
//房东 public class Host implements Rent { public void rent() { System.out.println("出租房屋"); } }
处理程序
package com.kuang.demo2; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 使用这个类自动生成代理对象 */ public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口 private Object target; public void setTarget(Object target) { this.target = target; }
//生成得到代理类 public Object getProxy(){ /** * 第一个参数:获取到当前类的getClassLoader * 第二个参数:获取到代理接口的接口 * 第三:获取到InvocationHandler,因为当前类实现了这个接口,所以可以使用this关键字 */ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); }
//处理代理实例,并返回处理结果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { lookHouse(); //动态代理的本质,就是使用反射实现 //第一个参数:表示代理的接口 //第二个参数;默认就可以了 Object result = method.invoke(target,args); return result; }
//拓展一个新的方法 public void lookHouse(){ System.out.println("带看房子"); } }
总结
不需要改变原来的代码,就可以扩展方法,也可以集中管理
使真实角色的方法代码可以纯粹,不用去管公共的方法
动态代理,代理的是接口,一般就是对应的一类业务
动态代理乐意代理多个类,只要实现同一个接口即可