博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
动态代理--jdk和cglib
阅读量:6770 次
发布时间:2019-06-26

本文共 4036 字,大约阅读时间需要 13 分钟。

一、含义

1、静态代理:简单,代理模式,是动态代理的理论基础。常见使用在代理模式

2、jdk动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用业务方法前调用InvocationHandler处理。代理类必须实现InvocationHandler接口,并且,JDK动态代理只能代理实现了接口的类,没有实现接口的类是不能实现JDK动态代理

3、cglib动态代理:可以直接代理类,使用字节码技术,不能对 final类进行继承。使用了动态生成字节码技术。

 

二、区别对比

JDK与Cglib动态代理对比?

1、JDK动态代理只能代理实现了接口的类,没有实现接口的类不能实现JDK的动态代理;

2、Cglib动态代理是针对类实现代理的,运行时动态生成被代理类的子类拦截父类方法调用,因此不能代理声明为final类型的类和方法;

动态代理和静态代理的区别?

1、静态代理在代理前就知道要代理的是哪个对象,而动态代理是运行时才知道;

2、静态代理一般只能代理一个类,而动态代理能代理实现了接口的多个类;

Spring如何选择两种代理模式的?

1、如果目标对象实现了接口,则默认采用JDK动态代理;

2、如果目标对象没有实现接口,则使用Cglib代理;

3、如果目标对象实现了接口,但强制使用了Cglib,则使用Cglib进行代理

三、.代码实现步骤

1、 jdk动态代理

步骤:

1.1、编写需要被代理的类和接口(我这里就是OrderServiceImpl、OrderService);

1.2、编写代理类(例如我这里的DynamicLogProxy),需要实现InvocationHandler接口,重写invoke方法;

1.3、使用Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)动态创建代理类对象,通过代理类对象调用业务方法。

 

2.cglib动态代理

cglib是针对类来实现代理的,它会对目标类产生一个代理子类,通过方法拦截技术对过滤父类的方法调用。代理子类需要实现MethodInterceptor接口

 

四、代码具体实现

public interface UserService {	void saveUser();}

  

public class UserServiceImpl implements UserService {		@Override	public void saveUser() {		System.out.println("IoC 演示 之UserService" );	}}

  

package com.kkb.spring.utils;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;import com.kkb.spring.service.UserService;import com.kkb.spring.service.UserServiceImpl;/** * 主要作用就是生成代理类 *  * @author think * */public class MyProxyUtils {	/**	 * 使用JDK的动态代理实现 它是基于接口实现的	 * 	 * @param serviceImpl	 * @return	 */	public static UserService getProxy(UserService service) {		// Proxy是JDK中的API类		// 第一个参数:目标对象的类加载器		// 第二个参数:目标对象的接口		// 第二个参数:代理对象的执行处理器		UserService userService = (UserService) Proxy.newProxyInstance(service.getClass().getClassLoader(),				service.getClass().getInterfaces(), new InvocationHandler() {					@Override					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {						System.out.println("记录日志-开始");						// 下面的代码,是反射中的API用法						// 该行代码,实际调用的是目标对象的方法						Object object = method.invoke(service, args);						System.out.println("记录日志-结束");						return object;					}				});		return userService;	}	/**	 * 使用CGLib动态代理技术实现 它是基于继承的方式实现的	 * 	 * @param service	 * @return	 */	public static UserService getProxyByCgLib(UserService service) {		// 创建增强器		Enhancer enhancer = new Enhancer();		// 设置需要增强的类的类对象		enhancer.setSuperclass(UserServiceImpl.class);		// 设置回调函数		enhancer.setCallback(new MethodInterceptor() {			// MethodProxy:代理之后的对象的方法引用			@Override			public Object intercept(Object object, Method method, Object[] arg, MethodProxy methodProxy)					throws Throwable {				long start = System.currentTimeMillis();				System.out.println("记录程序开始时间..." + start);				// 因为代理对象是目标对象的子类				// 该行代码,实际调用的是目标对象的方法				// object :代理对象				Object object2 = methodProxy.invokeSuper(object, arg);				long end = System.currentTimeMillis();				System.out.println("记录程序结束时间..." + end);				System.out.println("记录程序执行总时长..." + (end - start));				return object2;			}		});		// 获取增强之后的代理对象		UserService userService = (UserService) enhancer.create();		return userService;	}}

  

package com.kkb.spring.test;import org.junit.Test;import com.kkb.spring.service.UserService;import com.kkb.spring.service.UserServiceImpl;import com.kkb.spring.utils.MyProxyUtils;public class TestProxy {	@Test	public void testJDKProxy() {				//创建目标对象		UserService service = new UserServiceImpl();				//生成代理对象		UserService proxy = MyProxyUtils.getProxy(service);				//调用目标对象的方法		service.saveUser();				System.out.println("===============");		//调用代理对象的方法		proxy.saveUser();	}	@Test	public void testCgLibProxy() {				//创建目标对象		UserService service = new UserServiceImpl();				//生成代理对象		UserService proxy = MyProxyUtils.getProxyByCgLib(service);				//调用目标对象的方法		service.saveUser();				System.out.println("===============");		//调用代理对象的方法		proxy.saveUser();	}}

  

 

转载于:https://www.cnblogs.com/currystar/p/11050891.html

你可能感兴趣的文章
浅谈hibernate+入门实例
查看>>
Linux on Power 上的调试工具和技术
查看>>
Android系统移植与调试之-------&gt;如何添加一个adb wifi无线调试的功能【开发者选项】-【Wifi调试】...
查看>>
linux 防火墙操作
查看>>
Ubuntu中修改grub重启出现 Memtest86 解决方法
查看>>
VS 2012 标配 Asp.net MVC 和 Entity Framework - mybatisnet 可能就显得路子野 了
查看>>
kafka_java
查看>>
阿里云推出企业级智能协同办公方案 云桌面、云AP、云客服一应俱全
查看>>
安全性对于物联网在云端的应用至关重要
查看>>
背水一战 Windows 10 (20) - 绑定: DataContextChanged, UpdateSourceTrigger, 对绑定的数据做自定义转换...
查看>>
针对项目中用到可播放rtmp格式的jwplayer视频播放器
查看>>
使用libx264将I420编码为H.264
查看>>
java-对象的理解-对象在内存的存储
查看>>
为什么我们的web前端变的越来越复杂
查看>>
如何设置有利于网站优化的uRL结构?
查看>>
SaaS、云计算、软件:危险的“三角恋”
查看>>
创新Or模仿?浅谈“山寨”圈里的云计算
查看>>
《Linux From Scratch》第四部分:附录- 索引
查看>>
在 Swift Playgrounds 中使用 Core Data 模型
查看>>
ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现
查看>>