Spring基础学习(五)——基于JDK和CGlib的两种代理增强模式

一、基于JDK的代理增强

 实现原理:

  1.通过实现InvocationHandler接口创建自己的代理处理器

  2.通过反射机制得到目标类的所有构造方法和接口,并返回代理实例

  3.代理对象对目标类的方法进行增强(即添加方法执行前的逻辑和方法执行后的逻辑并返回目标类)

特点:JDK动态代理是面向接口的代理模式,基于JDK的环境,无需导入jar包,如果目标对象没有实现接口,则不能使用JDK代理

JDK代理代码实现:

1.目标类接口:

public interface Targe {

	public void sayHallo();
}

 2.目标类接口实现:

public class TargeImpl implements Targe{

	public void sayHallo() {
		System.out.println("我是明星我很大牌");
	}

}
3.JDK代理实现:
import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxyExample implements InvocationHandler{

	private Object targe = null;
	
	public Object bind(Object targe){
		this.targe = targe;
		//返回一个代理实例
		return Proxy.newProxyInstance(targe.getClass().getClassLoader(), targe.getClass().getInterfaces(),this);
		//方法参数:对象的所有构造方法,对象的所有接口,对象本身
	}
	
	public Object invoke(Object proxy,Method method,Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		System.out.println("我进入了事务所");
		System.out.println("执行某些逻辑");
		
		Object obj = method.invoke(targe, args);
		System.out.println("在真实调用了目标类方法之后的逻辑");
		
		return obj;
	}
}
4.测试类:
import org.junit.Test;

public class ProxyText {

	@Test
	public void JdkProxyText(){
		JDKProxyExample example = new JDKProxyExample();
		Targe proxyTarge = (Targe) example.bind(new TargeImpl());
		proxyTarge.sayHallo();
	}
}

5.输出结果:


二、基于CGlib的代理增强实现:

 实现原理:

 1.首先加载代理对象的Class文件,通过修改其字节码,将代理对象设置成目标类的子类

  2.设置代理对象继承目标类的构造方法(可以不做这一步),返回代理实例

 3.代理对象对目标类的方法进行增强(即添加方法执行前的逻辑和方法执行后的逻辑并返回目标类)

特点:需要导入CGlib库,和对XML文件配置通过字节码底层继承目标类生成代理类,故如果目标类用final修是则会失败,与jdk相比能够代理没有实现接口的类。 

CGlib代理增强的代码实现:

1.目标类:

public class TargeImpl implements Targe{

	public void sayHallo() {
		System.out.println("我是明星我很大牌");
	}

}
2.CGlib的代理实现

import java.lang.reflect.Method;

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



public class CGlibProxyExample implements MethodInterceptor {

	public Object getProxy(Class cls){
		
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(cls);//设置代理目标
		enhancer.setCallback(this);//回调
		enhancer.setClassLoader(cls.getClassLoader());
		return enhancer.create();//返回一个代理类(new intercept)
		
	}

	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		System.out.println("调用目标方法前");
		Object result = proxy.invokeSuper(obj, args);
		System.out.println("真是调用方法后的逻辑");
		return result;
	}

	
	
	
}

3.xml文件配置

<!-- true 表示底层使用cglib代理,false表示底层使用JDK代理,默认为false-->
	  <aop:config proxy-target-class="true"></aop:config>
4.测试类:


public class ProxyText {

	@Test
	public void JdkProxyText(){
		//基于JDK代理测试
		/*JDKProxyExample example = new JDKProxyExample();
		Targe proxyTarge = (Targe) example.bind(new TargeImpl());
		proxyTarge.sayHallo();*/
		//基于CGLib代码测试
		TargeImpl proxy = (TargeImpl) new CGlibProxyExample().getProxy(TargeImpl.class);
		proxy.sayHallo();
	}
}

5.结果



三、jdk与CGlib代理增强的比较

 JDK代理是面向接口的,如果目标类没有实现接口无法代理,是Spring的默认代理方式,创建代理速度快,而CGlib是字节码底层继承目标类来实现的,如果目标类被final修饰则会失败,但目标类不需要实现接口,需要导入CGlib.jar包,创建代理速度比jdk慢,但运行速度快

 四、使用注意:

 如果要被代理的对象是个实现类,那么Spring会使用JDK动态代理来完成操作(Spirng默认采用JDK动态代理实现机制)

 如果要被代理的对象不是个实现类那么,Spring会强制使用CGLib来实现动态代理。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值