代理模式是一种很常见的设计模式,在多线程、aop、远程代理等场景中均有体现,代理在我们的生活中也是很随处可见的。代理模式即为一个真实对象提供了一个代理对象,这个代理除了拥有真实对象的功能外,还能在不改变真实对象的情况下进行功能的增强且也能达到安全控制的效果。 静态代理需要定义接口(或类),代理对象和被代理对象都需要实现这个接口(或类)。为什么是静态的呢?是因为我们为每个真实对象提供代理对象的时候,代理对象都是先创建好的,即在程序中要使用代理必先有代理类。 在我们的web项目开发中,一般的业务逻辑(CRUD)实现写在Service层,但是当我们需要扩展Service层功能的时候由于原先的项目已稳定运行不能随意修改。假如有一个新的需求:在新增方法之前添加一个校验功能检查数据的正确性。下面提供几个做法: 可以看到在不改变原有代码前提下进行了功能增强是不是很妙,使用代理模式虽然并不能减少我们的代码量,但是能降低我们修改代码造成的风险,且使用代理模式各个角色更好的实现了业务的分工。但是静态代理也是有缺点的: 既然静态代理有问题,肯定有解决,那就是动态代理 动态代理和静态代理的角色都是一样的,区别在于静态代理的代理类需要我们提前写好,而动态代理的代理类是动态生成的,使用的是jdk的api动态在内存中构建代理对象。 实现jdk动态代理核心的两个类InvocationHandler、Proxy 需求:测试上面逻辑代码每个功能方法的运行效率,进行性能优化。 上面我们看到静态代理和JDK动态代理都是基于接口,目标对象都需要实现一个接口。如果目标对象并没有实现任何接口,这个时候就可以通过cglib代理来实现动态代理。 cglib基于AMS框架实现,需要导入四个jar包 被代理的类不能是final修饰,因为final不能被继承,会抛出java.lang.IllegalArgumentException 目标对象的方法如果为final/static代理对象不会执行目标对象的不会执行目标对象额外的增强方法 需求:在每个方法执行前新增日志打印功能。 我们都指定aop的底层就是代理,那么在spring中使用aop有什么效果呢?如下图,我们开发中都是纵向开发一个功能,当功能稳定运行但需要增强功能的时候,这就需要横向开发达到不影响原来逻辑的情况下完成补强。至于选择何种代理模式取决于你的项目需求。
一、前言
1、代理分类
2、代理角色
二、静态代理
1、静态代理理解
2、静态代理
3、demo
package com.spring.proxy.service; public interface UserService { void add(); void del(); void update(); void search(int id); }
package com.spring.proxy.service.impl; import com.spring.proxy.service.UserService; public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("新增加一条数据!"); } @Override public void del() { System.out.println("删除了一条数据!"); } @Override public void update() { System.out.println("更新了一条数据"); } @Override public void search(int id) { System.out.println("返回查找一条数据!"); } }
package com.spring.proxy.demo; import com.spring.proxy.service.UserService; public class UserServiceProxy implements UserService { private UserService userService; public void setUserService(UserService userService) { this.userService = userService; } @Override public void add() { valid(); userService.add(); } @Override public void del() { } @Override public void update() { } @Override public void search(int id) { } //进行功能的增强检验功能 private void valid() { System.out.println("检查数据合法性..."); } }
@Test public void testStaticProxy(){ UserServiceImpl userService = new UserServiceImpl(); UserServiceProxy proxy = new UserServiceProxy(); //设置代理对象 proxy.setUserService(userService); //通过代理调用新增功能 proxy.add(); } /** 结果: 检查数据合法性... 新增加一条数据! */
三、JDK的动态代理(基于接口)
1、动态代理理解
2、JDK的动态代理
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)
3、demo
package com.spring.proxy.dynamicProxy; import java.lang.reflect.Proxy; public class UserProxy { //可通过构造器或setter初始化目标对象 private Object target; public UserProxy(Object target) { this.target = target; } /** * 获取代理对象 */ public Object getProxy() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> { long startTime = System.nanoTime(); Object value = method.invoke(target, args); long endTime = System.nanoTime(); System.out.println(method.getName() + "方法耗时:" + (endTime - startTime)); return value; }); } }
@Test public void testDynamicProxy(){ //创建目标对象 UserService userService = new UserServiceImpl(); //创建代理对象 UserService proxy = (UserService) new UserProxy(userService).getProxy(); //通过代理对象调用目标对象方法 proxy.add(); proxy.del(); proxy.update(); proxy.search(); } /**结果 新增加一条数据! add方法耗时:96201 删除了一条数据! del方法耗时:25099 更新了一条数据 update方法耗时:51600 返回查找一条数据! search方法耗时:21700 */
通过调试可以看到proxy对象为动态生成的,根据传参生成UserServiceImpl代理类,再根据代理对象调用目标对象的方法,通过反射获取到Method对象调用实现类中的方法,args为实现方法的参数列表,进一步验证了我们上面的结论。四、cglib代理(基于类)
1、cglib代理理解
2、cglib动态代理
3、demo
package com.spring.proxy.cglibProxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class UserSerProxy implements MethodInterceptor { //目标对象 private Object target; public void setTarget(Object target) { this.target = target; } /** * 获取代理对象 */ public Object getProxy() { //创建Enhancer对象 Enhancer enhancer = new Enhancer(); //设置目标对象为父类 enhancer.setSuperclass(target.getClass()); //设置回调函数,参数实现MethodInterceptor的对象即当前对象 enhancer.setCallback(this); //创建子类对象即代理对象 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { log("准备执行" + method.getName()); return method.invoke(target, objects); } private void log(String msg) { System.out.println("[自定义日志:]" + msg); } }
@Test public void testCglibProxy(){ //创建目标对象 UserServiceImpl userService = new UserServiceImpl(); //获取代理对象 UserSerProxy userSerProxy = new UserSerProxy(); userSerProxy.setTarget(userService); UserServiceImpl proxy = (UserServiceImpl) userSerProxy.getProxy(); //通过代理对象调用目标对象的方法 proxy.add(); proxy.del(); proxy.update(); proxy.search(1); } /**结果: [自定义日志:]准备执行add 新增加一条数据! [自定义日志:]准备执行del 删除了一条数据! [自定义日志:]准备执行update 更新了一条数据 [自定义日志:]准备执行search 返回查找一条数据! */
五、代理模式深入理解
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算