设计模式之代理模式
代理模式(Proxy pattern)
- 抽象角色:定义代理角色和真实角色的公共对外方法
- 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用
- 代理角色:实现抽象,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作
代理对象和目标对象都要实现指定的接口
代理对象要包含目标对象
代理对象对照目标对象进行增强
静态代理(static proxy)
- 抽象角色
package designmode.proxy.staticproxy;
public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 订票
*/
void bookTicket();
/**
* 唱歌
*/
void sing();
/**
* 收尾款
*/
void collectMoney();
}
- 目标对象
package designmode.proxy.staticproxy;
public class RealStar implements Star{
@Override
public void confer() {
}
@Override
public void signContract() {
}
@Override
public void bookTicket() {
}
@Override
public void sing() {
System.out.println("周杰伦本人唱歌");
}
@Override
public void collectMoney() {
}
}
- 代理对象
package designmode.proxy.staticproxy;
public class ProxyStar implements Star{
private Star star;
public ProxyStar(Star star) {
this.star = star;
}
@Override
public void confer() {
System.out.println("面谈");
}
@Override
public void signContract() {
System.out.println("签合同");
}
@Override
public void bookTicket() {
System.out.println("订票");
}
@Override
public void sing() {
star.sing();
}
@Override
public void collectMoney() {
System.out.println("收尾款");
}
}
- 测试
package designmode.proxy.staticproxy;
public class Client {
public static void main(String[] args) {
Star real = new RealStar();
Star proxy = new ProxyStar(real);
proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing();
proxy.collectMoney();
}
}
动态代理(jdk代理)
抽象角色
package designmode.proxy.dynamicproxy;
public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 订票
*/
void bookTicket();
/**
* 唱歌
*/
void sing();
/**
* 收尾款
*/
void collectMoney();
}
真实角色
package designmode.proxy.dynamicproxy;
public class RealStar implements Star{
@Override
public void confer() {
System.out.println("和经纪人面谈");
}
@Override
public void signContract() {
System.out.println("和经纪公司签合同");
}
@Override
public void bookTicket() {
System.out.println("订票");
}
@Override
public void sing() {
System.out.println("周杰伦本人唱歌");
}
@Override
public void collectMoney() {
System.out.println("付尾款");
}
}
处理器类
package designmode.proxy.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class StarHandler implements InvocationHandler{
private Object realStar;
public StarHandler(ObjectrealStar) {
this.realStar = realStar;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj = null;
System.out.println("面谈,签合同,预付款,订票");
if(method.getName().equals("sing")) {
obj = method.invoke(realStar, args);
}
System.out.println("收尾款");
return obj;
}
}
测试
package designmode.proxy.dynamicproxy;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
Star realStar = new RealStar();
StarHandler handler = new StarHandler(realStar);
Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {Star.class}, handler);
proxy.sing();
}
}
CGLIB动态代理
利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
目标对象
package designmode.proxy.cglib;
public class TeacherDao {
public void teach() {
System.out.println("老师授课中,我是cglib代理,不需要实现接口");
}
}
代理实现
package designmode.proxy.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ProxyFactory implements MethodInterceptor{
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
// 返回一个代理对象,是target对象的代理对象
public Object getProxyInstance() {
// 创建一个工具类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(target.getClass());
// 设置回调函数
enhancer.setCallback(this);
//创建子类对象,即代理对象
return enhancer.create();
}
//重写intercept方法,会调用目标对象的方法
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("Cglib代理模式开始");
Object returnValue = arg1.invoke(target, arg2);
System.out.println("Cglib代理提交");
return returnValue;
}
}
测试
package designmode.proxy.cglib;
public class Client {
public static void main(String[] args) {
TeacherDao target = new TeacherDao();
TeacherDao proxy =(TeacherDao) new ProxyFactory(target).getProxyInstance();
proxy.teach();
}
}
注意:cglib支持jdk8以下的版本,8以上的版本报类型转换错误
参考资料:
https://www.jianshu.com/p/46d092bb737d