Java与形式之代理(Proxy)模式

Java与模式之代理(Proxy)模式

代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制原对象的引用。

代理模式的示意性实现类图如下


Java与形式之代理(Proxy)模式

  • 抽象主题角色:声明了真实主题与代理主题的共同接口,这样在可以使用真实主题的地方都可以使用代理主题。
  • 代理主题角色:包含了一个对真实主题角色的引用,从而可以在任何时候操作真实主题角色。

 代理模式的时序图如下

 
Java与形式之代理(Proxy)模式
代理模式是怎样工作的:

  • 代理主题并不改变主题的接口,因为模式的用意是不让客户端感觉到代理的存在。
  • 代理使用委派将客户端的调用传递给真实主题对象,代理起的到是一个传递请求的作用。
  • 代理主题在传递调用之前和之后都可以执行特定的操作,而不是单纯的传递请求。

JDK动态代理

jdk的动态代理是基于接口的,必须实现了某一个或多个任意接口才可以被代理,并且只有这些接口中的方法会被代理。

在Dao类的方法调用前输出xxx方法 start

public interface UserDao {
	public void save();
	public void delete();
}

 

public class UserDaoImpl implements UserDao {

	@Override
	public void delete() {
		// TODO Auto-generated method stub
		System.out.println("deleted");
	}

	@Override
	public void save() {
		// TODO Auto-generated method stub
		System.out.println("save");
	}

}

 

public class DaoProxy implements InvocationHandler {
	private Object target;
	
	public Object getTarget() {
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println(method.getName()+"  start!");
		method.invoke(target,args);
		return null;
	}
}

 

public static void main(String[] args) {
		UserDao uDao = new UserDaoImpl();
		DaoProxy log = new DaoProxy();
		log.setTarget(uDao);
		UserDao uDaoProxy  = (UserDao)Proxy.newProxyInstance(uDao.getClass().getClassLoader(),
				uDao.getClass().getInterfaces(), log);
		uDaoProxy.delete();
		uDaoProxy.save();
	}

 

运行结果
delete start!
deleted
save start!
save

 

CGlib 

  • cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
  • cglib封装了asm,可以在运行期动态生成新的class。
  • cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。

Spring中AOP是基于代理的思想来实现,其代理就是基于CGlib来实现的。

 

 

 

参考:《Java与模式》