设计模式之代理模式,静态代理和动态代理以及CGLIB代理

代理模式(Proxy pattern):

  • 核心作用: 通过代理,控制对对象的访问! 可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后 做后置处理。(即:AOP的微观实现!)
  • AOP(Aspect Oriented Programming面向切面编程)的核心实现机制!
  • 核心角色:
    抽象角色 – 定义代理角色和真实角色的公共对外方法
    真实角色 – 实现抽象角色,定义真实角色所要实现的业务逻辑, 供代理角色调用, 关注真正的业务逻辑!
    代理角色 – 实现抽象角色,是真实角色的代理,通过真实角色 的业务逻辑方法来实现抽象方法,并可以附加 自己的操作。
    在这里插入图片描述
  • 分 类:
    – 静态代理(静态定义代理类)
    – 动态代理(动态生成代理类)
    • JDK自带的动态代理
    • javaassist字节码操作库实现
    • CGLIB

1、静态代理

以游戏为例

/**
 * 抽象角色:游戏
 * @author Administrator
 */
public interface IGame {
	/**
	 * 登录
	 * @param username
	 * @param password
	 */
	void login(String username,String password);
	/**
	 * 打怪
	 */
	void killBoss();
	/**
	 * 升级
	 */
	void upGrade();
}
/**
 * 真实角色:玩家
 * @author Administrator
 */
public class GamePlayer implements IGame{
	
	private String name;
	
	public GamePlayer(String name){
		this.name=name;
	}
	@Override
	public void login(String username, String password) {
		System.out.println("登录名:"+username+"登录成功/n"+"欢迎玩家:"+this.name);
	}
	@Override
	public void killBoss() {
		System.out.println(this.name+"在打怪。。。");
	}
	@Override
	public void upGrade() {
		System.out.println(this.name+"升了一级。。。");
	}

}
/**
 * 代理角色:游戏代练
 * @author Administrator
 */
public class GamePlayProxy implements IGame{
	//被代理对象、真实对象
	private GamePlayer gamePlayer;
	//通过构造方法注入真实被代理对象
	public GamePlayProxy(GamePlayer gamePlayer){
		this.gamePlayer=gamePlayer;
	}
	@Override
	public void login(String username, String password) {
		System.out.println("代理开始登录。。。");
		this.gamePlayer.login(username, password);
		System.out.println("代理登陆成功。。。");
	}
	@Override
	public void killBoss() {
		System.out.println("代理操作账号打boss。。。");
		this.gamePlayer.killBoss();
	}
	@Override
	public void upGrade() {
		System.out.println("代理打完boss,升了一级");
		this.gamePlayer.upGrade();
		System.out.println("代理找玩家收费");
	}
	
}
/**
 * 测试
 * @author Administrator
 */
public class Client {
	public static void main(String[] args) {
		//代理出场
		IGame gamePlayerProxy = new GamePlayerProxy(new GamePlayer("雄霸天下"));
		//登录
		gamePlayerProxy.login("admin", "888888");
		//打boss
		gamePlayerProxy.killBoss();
		//升级
		gamePlayerProxy.upGrade();
	}
}

//输出结果
代理开始登录。。。
登录名:admin登录成功
欢迎玩家:雄霸天下
代理登陆成功。。。
代理操作账号打boss。。。
雄霸天下在打怪。。。
代理打完boss,升了一级
雄霸天下升了一级。。。
代理找玩家收费

2、JDK自带的动态代理

抽象角色和真实角色跟上面静态代理一样,在这就不重复写了

/**
 * 万能代理类:JDK自带的动态代理,要实现InvocationHandler
 * @author Administrator
 *
 */
public class DynamicProxy implements InvocationHandler{
	//被代理对象、真实对象
	private Object realObj;
	
	//通过构造函数传入一个真实对象
	public DynamicProxy(Object realObj) {
		this.realObj = realObj;
	}

	//代理核心,反射调用
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("代理对象之前可以做的事情。。。。。");
		//真实对象的方法反射调用
		Object result=method.invoke(this.realObj, args);
		
		System.out.println("代理对象之后可以做的事情。。。。。");
		return result;
	}
	/**
	 * 对外提供得到代理对象的实例(动态代理对象)
	 * @return
	 */
	public Object getProxyInstance(){
		//JDK自带的Proxy类的方法得到实例。
		//三个参数分别为:真实对象的类加载器、真实对象的接口、实现InvocationHandler的代理类
		Object newProxyInstance = Proxy.newProxyInstance(this.realObj.getClass().getClassLoader(), this.realObj.getClass().getInterfaces(), this);
		return newProxyInstance;
	}	
}
/**
 * 测试
 * @author Administrator
 *
 */
public class Client {
	public static void main(String[] args) {
		//代理出场
		DynamicProxy proxy = new DynamicProxy(new GamePlayer("雄霸天下"));
		//得到代理实例返回的是接口,强转
		IGame gamePlayer=(IGame)proxy.getProxyInstance();
		//登录
		gamePlayer.login("admin", "888888");
		//打boss
		gamePlayer.killBoss();
		//升级
		gamePlayer.upGrade();
	}
}

//输出结果
代理对象之前可以做的事情。。。。。
登录名:admin登录成功
欢迎玩家:雄霸天下
代理对象之后可以做的事情。。。。。
代理对象之前可以做的事情。。。。。
雄霸天下在打怪。。。
代理对象之后可以做的事情。。。。。
代理对象之前可以做的事情。。。。。
雄霸天下升了一级。。。
代理对象之后可以做的事情。。。。。

3、CgLib动态代理(最好的新建maven项目导包)

真是对象不需要再实现接口

/**
 * 真实角色:玩家
 * @author Administrator
 */
public class GamePlayer {
	private String name;
	public GamePlayer(String name){
		this.name=name;
	}
	public void login(String username, String password) {
		System.out.println("登录名:"+username+"登录成功\n"+"欢迎玩家:"+this.name);
	}
	public void killBoss() {
		System.out.println(this.name+"在打怪。。。");
	}
	public void upGrade() {
		System.out.println(this.name+"升了一级。。。");
	}

}
/**
 * CgLib动态代理要去实现MethodInterceptor
 * @author Administrator
 *
 */
public class CgLibProxy implements MethodInterceptor{
	
	//被代理对象、真实对象
	private Object realObj;
		
	//通过构造函数传入一个真实对象
	public CgLibProxy(Object realObj) {
		this.realObj = realObj;
	}
	//Cglib代理核心,反射调用
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		System.out.println("Cglib代理对象之前可以做的事情。。。。。");
		//真实对象的方法反射调用
		Object result=method.invoke(this.realObj, args);
		
		System.out.println("Cglib代理对象之后可以做的事情。。。。。");
		return result;
	}
	
	/**
	 * 对外提供得到代理对象的实例(动态代理对象)
	 * @return
	 */
	public Object getProxyInstance(){
		//1、创建Enhancer工具类实例
		Enhancer enhancer=new Enhancer();
		//2、加载真实类
		enhancer.setSuperclass(this.realObj.getClass());
		//3、设定MethodInterceptor的实现
		enhancer.setCallback(this);
		return enhancer;
	}
}
/**
 * 测试
 * @author Administrator
 *
 */
public class Client {
	public static void main(String[] args) {
		//代理出场
		CgLibProxy proxy = new CgLibProxy(new GamePlayer("雄霸天下"));
		GamePlayer gamePlayer=(GamePlayer)proxy.getProxyInstance();
		//登录
		gamePlayer.login("admin", "888888");
		//打boss
		gamePlayer.killBoss();
		//升级
		gamePlayer.upGrade();
	}
}

//测试结果
Cglib代理对象之前可以做的事情。。。。。
登录名:admin登录成功
欢迎玩家:雄霸天下
Cglib代理对象之后可以做的事情。。。。。
Cglib代理对象之前可以做的事情。。。。。
雄霸天下在打怪。。。
Cglib代理对象之后可以做的事情。。。。。
Cglib代理对象之前可以做的事情。。。。。
雄霸天下升了一级。。。
Cglib代理对象之后可以做的事情。。。。。
总结:

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值