代理模式
参考博客:
定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
假设你的同事写了一个登录业务实现类,同事离职了,你接了他的锅,现在PM让你在登录功能的基础上添加登录日志。你有两个选择,一是修改同事的已经写好的代码,二是写一个代理,在不改动代码的基础上,增加日志功能。
编写代理的好处是,不用修改别人的代码,符合软件设计的开闭原则。
代理模式分为:
- 静态代理
- 动态代理
静态代理
// 服务接口 唱歌
public interface Singing {
void singSong();
}
// 服务实现类 明星类 会唱歌
public class Star implements Singing {
@Override
void singSong(){
system.out.printf("我是明星我在唱歌");
}
}
// 代理类 明星代理 也可以唱歌
public class StarProxy implements Singing {
private Say say;
// 注入他代理的明星
public StarProxy(fianl Say say){
this.say = say;
}
@Override
void singSong(){
// do something before singSong
system.out.printf("代理人在卖门票");
// 代理让明星唱歌,他可以在明星唱歌前,唱歌后做其他业务
say.singSong();
system.out.printf("代理人在...");
// do something after singSong
}
}
// 测试类
public class ProxyTest {
public static void main(String[] args) {
Star star = new Star();
StarProxy proxy = new StarProxy(star);
proxy.singSong();
}
}
可以看到静态代理都有以下特点:
- 业务类(明星类)和 代理类都实现了同一个接口
- 最终由代理类执行业务类方法,并由代理类扩展业务
动态代理
在java中动态代理比较常见的实现有基于jdk的实现和基于cglib的实现。
所谓的动态顾名思义就是,不用手动编写代理类,实现代理功能。
利用jdk反射机制实现动态代理
利用反射机制实现代理原理是一样的,只是在代码运行到时候自动新建代理类。目标对象必须实现接口才能使用jdk代理。
// java.lang.reflect.Proxy 类 获取代理实例工厂方法
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
- ClassLoader loader :目标对象类加载器
- Class<?>[] interfaces:目标类的接口
- InvocationHandler h:目标类的句柄
// 代理工厂
public class ProxyFactory{
//维护一个目标对象
private Object target;
public ProxyFactory(Object target){
this.target=target;
}
//给目标对象生成代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 可以根据method的name来指定特定的方法代理
System.out.println("开始事务2");
//执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务2");
return returnValue;
}
}
);
}
}
利用cglib实现动态代理
cglib实现代理的原理是通过生成目标子类来实现代理的。所以,要求目标类不能是final类,代理的方法也不能是final/static修饰的方法。
// 代理工厂
public class ProxyFactory implements MethodInterceptor{
//维护目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("开始事务...");
//执行目标对象的方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务...");
return returnValue;
}
}