代理模式

代理模式


代理模式是常用设计模式之一,当一个对象不适合或者不能直接引用另一个对象时,使用代理对象做中介,通过代理对象访问目标对象。 并且可在代理对象中扩展目标对象的功能

如同经纪人代办事情一样,客户通过代理对象访问目标对象,可以实现权限的控制。同时代理对象可以代处理一些复杂的事务,减轻目标对象的负担。

java中代理模式有三种实现:

静态代理

  1. 创建目标类的接口 ITarget.java
    • 提供一个hadleThings 事件处理方法
package cc.ggbond.proxy;

public interface ITarget {
	
	public void handleThings();

}
  1. 创建目标类 Target.java
    • 目标类实现ITarget接口 实现其中的处理方法.
package cc.ggbond.proxy;

public class Target implements ITarget{
	@Override
	public void handleThings() {
		// TODO Auto-generated method stub
		System.out.println("目标对象处理...");
	}
}
  1. 创建代理类MyProxy.java
    • 代理类需要与目标类实现相同的接口,重写方法,可在此处扩展目标对象的功能。
    • 在类中维护一个目标类对象的引用,通过这个引用来访问目标对象的方法。
package cc.ggbond.proxy;

public class MyProxy implements ITarget{
	private static ITarget target = new Target(); ;

	@Override
	public void handleThings() {
		System.out.println("代理对象预处理...");
		target.handleThings();
		System.out.println("代理对象处理结束...");
	}
}
  1. 创建客户类使用代理对象实现需要的操作:
package cc.ggbond.proxy;
import org.junit.Test;

public class Clinet {

	@Test
	public void testProxy() {
		ITarget proxy = new MyProxy();
		proxy.handleThings();
	}
}

运行结果:

代理对象预处理… 目标对象处理… 代理对象处理结束…

可见客户通过代理对象实现了目标对象的功能,并且在代理对象中扩展了功能。实现预处理和善后。

动态代理

动态代理解决了静态代理不易维护和代理类多的缺点。动态生成代理对象。仅需一个代理工厂类

java中主要有两种动态代理方式:

JDK提供的Proxy类

还是上面的例子,Target类 和 ITarget类保持不变

package cc.ggbond.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;   //jdk 反射包中提供代理类

public class MyProxy<T>{

	private T target;  //维护目标对象的引用,通过构造函数传入

	public MyProxy(T target) {
		this.target = target;
	}
	//获取代理对象的方法
	public Object getProxyInstance() {
		return Proxy.newProxyInstance(
				target.getClass().getClassLoader(),  //第一个参数是目标对象的类加载器
				target.getClass().getInterfaces(), //目标对象实现的接口
				//回调接口,对于目标对象的每个方法,通过反射获取方法参数
				//然后回调访问这个接口的invoke方法
				new InvocationHandler() {  
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						//在此处扩展目标类的功能
						System.out.println("代理开始....");
						if(method.getName().equals("save")) {
							Object returnValue = method.invoke(target, args);
							System.out.println("代理结束....");
							return returnValue;
						}
						return null;
					}
				});
	}
}
package cc.ggbond.proxy;
import org.junit.Test;

public class Clinet {

	@Test
	public void testProxy() {
		ITarget proxy = (ITarget) new MyProxy(new Target()).getProxyInstance();
		proxy.handleThings();
	}
}

Spring核心包中的Cglib代理

Cglib代理不需要目标类实现接口. Cglib代理封装在了封装在spring核心包spring-core 中.使用需要先导入此包。 Cglib产生的代理对象是目标对象的子类 Calib代理广泛应用于Aop

使用cglib代理MyProxy.java如下:

package cc.ggbond.proxy;

import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
//代理类需要实现MethodInterceptor接口
public class MyProxy <T> implements MethodInterceptor{
	T taget;
	
	public MyProxy(T taget) {
		super();
		this.taget = taget;
	}
	//获取代理对象实例
	public Object getProxyInstance() {
	    //通过这个Enhancer增强工厂来创建代理对象
		Enhancer en = new Enhancer();
		//设置代理对象的父类
		en.setSuperclass(taget.getClass());
		//设置访问方法时的回调接口
		en.setCallback(this);
		//创建代理对象并返回
		return en.create();
	}

//重写intercept方法,这个是代理对象的回调方法
	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("cglib代理开始...");
		Object returnValue = arg1.invoke(taget, arg2);
		System.out.println("cglib代理结束...");
		return returnValue;
	}
}

0

Powered by Jekyll and Theme by solid