jdk动态代理和cglibo动态代理

当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象。按照代理对象的创建时期不同,可以分为两种:
静态代理:程序员事先写好代理对象类,在程序发布前就已经存在了;
动态代理:应用程序发布后,通过动态创建代理对象。
其中动态代理又可分为:

1.JDK动态代理

此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑。

代理模式在实际使用时需要指定具体的目标对象,如果为每个类都添加一个代理类的话,会导致类很多,同时如果不知道具体类的话,怎样实现代理模式呢?这就引出动态代理。

 

JDK动态代理只能针对实现了接口的类生成代理。

下面写一个简单的demo实现jdk动态代理:

1、首先创建一个Car的接口类:

public interface Car {

	public void move();
}
2、创建一个对Car的实现类Carmove

public class Carmove implements Car{

	@Override
	public void move() {
		// TODO Auto-generated method stub
		System.out.println("汽车正在运行");
	}
}
3、创建一个ProxyFactory代理类实现一个InvocationHandler类重写invoke方法

public class ProxyFactory {
	//维护一个目标对象
	private Object target;
	public ProxyFactory(Object target) {
		super();
		this.target = target;
	}
	//给目标对象生成代理对象
	public Object getProxyInstance(){
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
			    new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("JDK动态代理开始");
						Object returnValue = method.invoke(target);
						System.out.println("JDK动态代理结束");
						return returnValue;
					}
				});
	}
}

4、编写测试类进行测试:

public class TestDongTaiDaiLi {

	public static void main(String[] args) {
		//定义目标对象
		Carmove carmove = new Carmove();
		//System.out.println(carmove.getClass().getClassLoader());
		//System.out.println(carmove.getClass().getInterfaces());
		//给目标对象创建代理对象
		Car proxy = (Car)new ProxyFactory(carmove).getProxyInstance();
		//System.out.println(proxy.getClass().getClassLoader());
		//System.out.println(proxy.getClass().getInterfaces());
		//触发目标对象的接口方法
		proxy.move();
	}

}

2.CGLIB代理

CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。

如果目标对象没有实现接口,则默认会采用CGLIB代理;

如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。

 1、创建一个需要被cglib代理的代理类:

public class CglibCarmove {
	public void say() {
		System.out.println("Cglib实体类");
	}
}

2、创建cgilb代理类:

import java.lang.reflect.Method;

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

/**
 * 
 * cglib动态代理不需要面向接口,可以代理简单类,但由于动态代理对象是继承真实主题实现类的,
 * 因此要求真实主题实现类不能是final的。
 * 
 * @date: 2017年5月3日 上午10:14:49
 */
public class CglibDongleTaiDaiLi implements MethodInterceptor {
	private Enhancer enhancer = new Enhancer();
	 public Object getProxy(Class clazz){  
		  //设置需要创建子类的类  
		  enhancer.setSuperclass(clazz);  
		  enhancer.setCallback(this);  
		  //通过字节码技术动态创建子类实例  
		  return enhancer.create();  
		 } 
	@Override
	public Object intercept(Object target, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
		System.out.println("CGlib动态代理开始");
		Object result = proxy.invokeSuper(target, arg2);
		System.out.println("CGlib动态代理结束");
		return result;
	}
}

3、编写测试类进行测试
public class TestCglibDongTaiDaiLi {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		CglibDongleTaiDaiLi proxy = new CglibDongleTaiDaiLi();
		//通过生成子类的方式创建代理类
		CglibCarmove proxyImp =(CglibCarmove)proxy.getProxy(CglibCarmove.class);
		//调用实体类的say方法
		proxyImp.say();
	}
}

CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。

AOP包括切面(aspect)、通知(advice)、连接点(joinpoint),实现方式就是通过对目标对象的代理在连接点前后加入通知,完成统一的切面操作。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值