对代理模式还不懂的朋友可以先看看这篇静态代理模式:静态代理模式
动态代理是指动态的生成
代理类
真实对象和接口是已经存在了的
1、动态代理和静态代理的角色是一样的;
2、动态代理的代理类是动态生成的;
动态代理分为两类,一类是基于几口的动态代理,一个是基于类的动态代理
a) 基于接口的动态代理-----jdk动态代理
b) 基于类的动态代理----cglib
4、jdk动态代理
关键的两个类: proxy类 和 invocationHandler接口
invocationHandler 是代理实例的 调用处理程序 实现的接口,
有一个方法是invoke (object proxy , Method method object [ ] args );
该方法 在代理实例上 处理方法调用 并返回结果;
proxy -- 被代理的对象;
method -- 对应的是代理实例调用的接口方法的Method实例;(被代理的方法)
args -- 方法调用所需要的参数数组
proxy 提供用于创建动态代理类和实例的静态方法
//伪代码
其中有个重要的方法 newProxyInstance(类加载器, 代理类要实现的接口,invocationHandler)
代码示例:
//出租的抽象接口
public interface Rent {
void Rent();
}
//被代理的角色
public class Host implements Rent{
@Override
public void Rent() {
System.out.println("房东要租房");
}
}
//代理类
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
Object result = method.invoke(target, args);
fare();
return result;
}
public Object getProxy(){
/**
* 利用jdk的Proxy这个类来为我们动态的生成代理类
* this.getClass().getClassLoader(), 通过这个本身这个类的类加载器来加载新的代理类
* target.getClass().getInterfaces(), 得到抽象类的接口
* this 需要的是InvocationHandler 而proxy这个类实现了InvocationHandler
*/
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
public void seeHouse(){
System.out.println("中介带房东看房");
}
public void fare(){
System.out.println("中介收取一波中介费");
}
}
//测试类
public class Test {
public static void main(String[] args) {
Host host = new Host();
ProxyInvocationHandler ih = new ProxyInvocationHandler();
ih.setTarget(host);
Rent r = (Rent)ih.getProxy();
r.Rent();
}
}
代码输出结果:
中介带房东看房
房东要租房
中介收取一波中介费
项目中稍作改进:
房东要租房
中介收取一波中介费
项目中稍作改进:
我们增加UserService和UserServiceImpl实现类;
在ProxyInvocationHandler中 我们模拟增加打印日志的功能,增加log();
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
Object result = method.invoke(target, args);
log(method.getName());
fare();
return result;
}
public Object getProxy(){
/**
* 利用jdk的Proxy这个类来为我们动态的生成代理类
* this.getClass().getClassLoader(), 通过这个本身这个类的类加载器来加载新的代理类
* this.getClass().getInterfaces(), 得到实现
* this 需要的是InvocationHandler 而proxy这个类实现了InvocationHandler
*/
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
public void log(String MethodName){
System.out.println("执行了:"+MethodName+"方法");
}
public void seeHouse(){
System.out.println("中介带房东看房");
}
public void fare(){
System.out.println("中介收取一波中介费");
}
}
测试类改为:
public class Test {
public static void main(String[] args) {
UserService user = new UserServiceImpl();
ProxyInvocationHandler ih = new ProxyInvocationHandler();
ih.setTarget(user);
UserService r = (UserService)ih.getProxy();
r.add();
}
}
输出结果为:
中介带房东看房
增加一名新用户
执行了:add方法
中介收取一波中介费
可以看到 打印了 执行了:add方法 这就是我们常用的SpringAOP来做日志管理的原理;