参考:狂神说java
1.静态代理
代理模式的好处:
- 可以使真实角色的操作更加纯粹,不用再去关注一些公共的事情
- 公共的的业务由代理完成,实现了业务的分工
- 公共业务发生扩展时变的更加集中和方便
缺点:
- 当类变多了,代理类随之增加,工作量就变大了,开发效率低
2.动态代理
通过反射实现
分为2类:基于类的动态代理,基于接口的动态代理
- 基于接口 — JDK动态代理
- 基于类: cglib
- java字节码: javasist
主要使用2个类: Proxy,InvocationHandler
Proxy
InvocationHandler
3.手动实现日志的动态代理
接口
写一个租赁接口
public interface Rent {
void rentHouse();
}
实现类
public class RentService implements Rent {
@Override
public void rentHouse() {
System.out.println("租房子");
}
}
代理类
实现租赁接口
public class ProxyInvocationHandle implements InvocationHandler {
private Object object;
public void setObject(Object object) {
this.object = object;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
}
//处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object invoke = method.invoke(object, args);
return invoke;
}
//日志
private void log(String msg){
System.out.println("执行了"+msg+"方法");
}
}
测试
public class Test {
public static void main(String[] args) {
Rent rent = new RentService();
//代理角色
ProxyInvocationHandle pih = new ProxyInvocationHandle();
//设置代理对象
pih.setObject(rent);
//得到代理
Rent proxy = (Rent)pih.getProxy();
//执行代理方法
proxy.rentHouse();
}
}
到这里应该很多人会有疑问,invoke方法是什么时候调用的?怎么调用的?
4.动态代理的原理
- 通过实现 InvocationHandler 接口创建自己的调用处理器;
- 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
- 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
- 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。