天天看点

Java设计模式-代理模式定义优缺点实现

最近学习到设计模式,现总结个人学习代理模式内容【更加关注过程,对被代理对象完全控制】。

上一篇:Java设计模式-委派模式

文章目录

  • 定义
  • 优缺点
    • 优点
    • 缺点
  • 实现
    • CGLIB代理
      • 代码
      • 测试
    • JDK代理
      • 代码
      • 测试
    • 对比

定义

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用

优缺点

优点

  • (1).职责清晰,不用关心其他非本职责的事务。
  • (2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。
  • (3).高扩展性 [1]

缺点

  • 需要重新创建不可见对象。达到重写的目的。
  • 使用到了反射,降低了性能。

实现

CGLIB代理

代码

代理对象需要实现MethodInterceptor,属于cglib.jar包。

cglib内部创建一个对象,继承我们的对象[LoginWorkflow ],在创建的对象上重写了父类的方法,但是还是会使用父类的逻辑,而代理代码,则在业务逻辑前后添加其他业务逻辑。

Java设计模式-代理模式定义优缺点实现
/**
 * 登录流程
 * @author cc百川
 */
public class LoginWorkflow {
	public String doSubmit(){
		System.out.println("正在登录");
		return "登录成功";
	}
}
public class ProxyLog implements MethodInterceptor{
	public Object install(Class clazz) throws Exception{
		Enhancer enhancer = new Enhancer();
		//告诉cglib,生成的子类需要继承哪个父类
		enhancer.setSuperclass(clazz);
		enhancer.setCallback(this);//设置回调,告诉继续执行业务代码的类
		
		//生成源代码,编译成class文件,加载到JVM中,并返回被代理对象
		return enhancer.create();//创建被代理对象
	}
	@Override
	public Object intercept(Object obj, Method arg1, Object[] arg2,
			MethodProxy proxy) throws Throwable {
		System.out.println("代理登录前处理业务逻辑,判断是否规定时间登录");
		//该obj的引用是由CGLib给我们new出来的,这个是被代理对象的子类,子类引用强转父类,这时就可以操作父类的属性 
		String res = (String) proxy.invokeSuper(obj, arg2);
		System.out.println("代理登录后处理日志相关等");
		return res+",代理添加了日志";
	}
}
           

测试

Java设计模式-代理模式定义优缺点实现

JDK代理

代码

jdk代理核心实现InvocationHandler。

jdk代理需要借助接口,也就是被代理者实现一个接口【这里是Workflow】。

jdk实现代理过程

  • 1.拿到被代理对象的引用,然后获取它的接口
  • 2.JDK代理重新生成一个类,同时实现我们给的代理对象所实现的接口
  • 3.把被代理对象的引用也拿到了
  • 4.重新动态生成一个class字节码
  • 5.然后编译
    Java设计模式-代理模式定义优缺点实现
/**
 * 流程提交
 * @author cc百川
 */
public interface Workflow {
	String doSubmit();
}

/**
 * 登录流程
 * @author cc百川
 */
public class LoginWorkflow implements Workflow{
	public String doSubmit(){
		System.out.println("正在登录");
		return "登录成功";
	}
}

/**
 * 代理登录 jdk代理核心实现InvocationHandler
 * @author cc百川
 */
public class ProxyLog implements InvocationHandler{
	//用于保留被代理对象的引用
	private Workflow wf;
	
	//获取被代理的对象【资料】
	public Object install(Workflow wf) {
		this.wf = wf;
		Class cs = wf.getClass();
		return Proxy.newProxyInstance(cs.getClassLoader(), cs.getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("代理登录前处理业务逻辑,判断是否规定时间登录");
		String res = (String) method.invoke(this.wf, args);//执行原业务逻辑
		System.out.println("代理登录后处理日志相关等");
		return res+",代理添加了日志";
	}
}
           

测试

通过代理的方式,可以在执行业务代码前后添加逻辑

Java设计模式-代理模式定义优缺点实现

对比

JDK的动态代理是通过接口来进行强制转换的,生成以后的代理对象,可以强制转换为接口。

CGLib的动态代理是通过生成一个被代理对象的子类,然后重写父类的方法。子类引用强转给父类【被代理类】,从而调用对象方法。

日常对代理模式,常见有AOP,以及产品二开等,达到无侵入修改【后期举例】。

以上仅为个人学习,如果错误望指出,谢谢。

继续阅读