AOP编程之JDK动态代理和Cglib动态代理

最近开发过程中遇到一些问题,为了可以好好的解决,研究了几天的动态代理。记下来,怕以后忘记了。

动态代理适用的情景:

某个类的某个方法已经做好了,你在不想或者不能改动源代码的情况下,要做一些额外的操作,这时候就可以使用代理设计模式。

例如,周杰伦要举行新唱片的的签名发布会,他总不能自己去布置会场吧。所以他就请了他的经理人Kim去帮忙布置场地罗,这个Kim就是属于代理的角色了。他要在Joy签名会之前去布置场地,签名会之后清理场地。

下面我们来看看JDK代理怎么做的。

1.首先Joy同学需要先声明自己有一个签名会,也就是interface。然后再去开这个签名会。

public interface Joy {
	public void holdSignature();
}

public class JoyImpl implements Joy{
	public void holdSignature() {
		System.out.println("joy say:大家好,我是Joy,今天我在这里举行签名会哦...");
	}
}



2.然后我们的JDK代理就出场了

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//这是专门帮人家布置场地的JDK代理
public class JDKProxy implements InvocationHandler{
	//要代理的对象,也即是帮哪个明星做场地啦,今天可能是Joy,明天可能就是SHE了
	private Object star;
	public JDKProxy(Object star) {
		this.star = star;
	}
	
	public Object getProxySatr(){
		return Proxy.newProxyInstance(
				star.getClass().getClassLoader(), 
				star.getClass().getInterfaces(),
				this);
	}
	public Object invoke(Object obj, Method method, Object[] params)
			throws Throwable {
		System.out.println("jdk say:签名会开始之前,我要帮忙布置场地...");
		//明星开始他的签名会了
		Object result = method.invoke(star, params);
		System.out.println("jdk say:签名会结束了,我要清理场地。");
		return result;
	}

}



3.双方都准备就绪了,我们现在开始签合同工作了。

	public static void main(String[] args) {
		//jdkProxy代理接到order是帮joy布置场地呢。
		JDKProxy jdkProxy = new JDKProxy(new JoyImpl());
		//请出代理的明星,让他签名去咯
		Joy joy = (Joy) jdkProxy.getProxySatr();
		joy.holdSignature();
	}

可以看到最后的结果是:

jdk say:签名会开始之前,我要帮忙布置场地...

joy say:大家好,我是Joy,今天我在这里举行签名会哦...

jdk say:签名会结束了,我要清理场地。


大家可以发现,Joy开演唱会之前还有做一次声明,多么让人不爽快的interface啊。所以SHE开签名会的时候就换了一个叫cglib的代理。

下面来看cglib代理是怎么做的。

1.首先,SHE的演唱会还是要自己去开的。

public class SHE {
	public void musicShow() {
		System.out.println("she say:大家好,我们是SHE,下面为大家带来《星光》....");
	}
}


2.然后我们的Cglib其实是一家公司来的员工了,他可以为好多的明星布置会场的。成立这个比较好使代理公司,总的多投入点成本吧。

引入asm-3-3-1.jar和cglib-2.2.jar

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{
	public Enhancer enhancer = new Enhancer();
	
	public<T> Object getCglibProxy(Class<T> star){
		//指定这次要伺候的明星
		enhancer.setSuperclass(star);
		//要做什么呢?就是下面的intercept里面干的事
		enhancer.setCallback(this);
		//合约签订,把你的暂时仆人送过去服务你了。
		return enhancer.create();
	}

	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		System.out.println("cglib say:我在布置演唱会的场地.....");
		//boss可以开演唱会了
		Object result = proxy.invokeSuper(obj, args);
		
		System.out.println("cglib say:演唱会结束了,我在清理场地.....");
		return result;
	}
}


3.接下来就是签约工作了

public static void main(String[] args) {
		CglibProxy cglibProxy = new CglibProxy();
		SHE she = (SHE) cglibProxy.getCglibProxy(SHE.class);
		she.musicShow();
	}


4.最后你会发现,演唱会灰常的成功啦。

cglib say:我在布置演唱会的场地.....

she say:大家好,我们是SHE,下面为大家带来《星光》....

cglib say:演唱会结束了,我在清理场地.....


对比JDK代理和Cglib代理可以发现,JDK多了一个接口。

为什么JDK代理只能针对接口呢?

JDK动态代理的原理是根据定义好的规则,用传入的接口创建一个新类,这就是为什么采用动态代理时为什么只能用接口引用指向代理,而不能用传入的类引用执行动态类,有兴趣的自己去查源代码哈。

而Cglib则采用ASM工具,直接修改字节码。所以不用接口规范。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值