代理模式是SpringAOP的底层
分类:动态代理和静态代理
10.1、静态代理
代码步骤:
1、接口
package pojo;
public interface Host {
public void rent();
}
2、真实角色
package pojo;
public class HostMaster implements Host{
public void rent() {
System.out.println("房东要出租房子");
}
}
3、代理角色
package pojo;
public class Proxy {
public Host host;
public Proxy() {
}
public Proxy(Host host) {
super();
this.host = host;
}
public void rent() {
seeHouse();
host.rent();
fee();
sign();
}
//看房
public void seeHouse() {
System.out.println("看房子");
}
//收费
public void fee() {
System.out.println("收中介费");
}
//合同
public void sign() {
System.out.println("签合同");
}
}
4、客户端访问代理角色
package holle4_proxy;
import pojo.Host;
import pojo.HostMaster;
import pojo.Proxy;
public class My {
public static void main(String[] args) {
//房东要出租房子
Host host = new HostMaster();
//中介帮房东出租房子,但也收取一定费用(增加一些房东不做的操作)
Proxy proxy = new Proxy(host);
//看不到房东,但通过代理,还是租到了房子
proxy.rent();
}
}
代码翻倍:几十个真实角色就得写几十个代理
AOP横向开发
10.2、动态代理
动态代理和静态角色一样,动态代理底层是反射机制
动态代理类是动态生成的,不是我们直接写好的!
动态代理(两大类):基于接口,基于类
- 基于接口:JDK的动态代理【使用ing】
- 基于类:cglib
- java字节码实现:javasisit
了解两个类
1、Proxy:代理
2、InvocationHandler:调用处理程序
实例:
接口 Host.java
//接口
package pojo2;
public interface Host {
public String rent(String hostName);
}
接口Host实现类 HostMaster.java
//接口实现类
package pojo2;
public class HostMaster implements Host{
public String rent(String hostName) {
System.out.println("房东要租房子:"+hostName);
return "老贵了";
}
}
代理角色的处理程序类 ProxyInvocationHandler.java
package pojo2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
///用这个类,自动生成代理
public class ProxyInvocationHandler implements InvocationHandler {
// Foo f =(Foo) Proxy.NewProxyInstance(Foo. Class.GetClassLoader(),
// new Class<?>[] { Foo.Class },
// handler);
// 被代理的接口
public HostMaster hostMaster ;
public void setHostMaster(HostMaster hostMaster) {
this.hostMaster = hostMaster;
}
// 得到生成的代理类
public Object getProxy() {
// newProxyInstance() -> 生成代理对象,就不用再写具体的代理类了
// this.getClass().getClassLoader() -> 找到加载类的位置
// hostMaster.getClass().getInterfaces() -> 代理的具体接口
// this -> 代表了接口InvocationHandler的实现类ProxyInvocationHandler
return Proxy.newProxyInstance(this.getClass().getClassLoader(), hostMaster.getClass().getInterfaces(), this);
}
// 处理代理实例并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
// 动态代理的本质,就是使用反射机制实现的
// invoke()执行它真正要执行的方法
Object result = method.invoke(hostMaster, args);
fee();
return result;
}
public void seeHouse() {
System.out.println("看房子");
}
public void fee() {
System.out.println("收中介费");
}
}
用户类 My2.java
package holle4_proxy;
import pojo2.Host;
import pojo2.Host2;
import pojo2.HostMaster;
import pojo2.ProxyInvocationHandler;
public class My2 {
public static void main(String[] args) {
//真实角色
HostMaster hostMaster = new HostMaster();
//代理角色,现在没有;用代理角色的处理程序来实现Host接口的调用
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//pih -> HostMaster接口类 -> Host接口
pih.setHostMaster(hostMaster);
//获取newProxyInstance动态生成代理类
Host proxy = (Host) pih.getProxy();
proxy.rent();
}
}
弹幕评论:
什么时候调用invoke方法的?
代理实例调用方法时invoke方法就会被调用,可以debug试试
改为万能代理类
///用这个类,自动生代理
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
public Object target;
public void setTarget(Object target) {
this.target = target;
}
// 得到生成的代理类 -> 固定的代码
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
// 处理代理实例并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 动态代理的本质,就是使用反射机制实现的
// invoke()执行它真正要执行的方法
// seeHouse();
Object result = method.invoke(target, args);
// fee();
return result;
}
}