代理模式详解:静态代理、JDK动态代理与Cglib动态代理 (2)

定义JdkProxy类实现InvocationHandler接口,实现invoke()方法,并对业务逻辑进行增强

package com.rangers.proxy.jdkProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public class JdkProxy implements InvocationHandler { private Object target; public JdkProxy() { } public JdkProxy(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 此处对目标方法进行增强 System.out.println("对转账人身份校验。。"); Object result = method.invoke(target, args); System.out.println("进行日志记录。。"); return result; } }

新建测试类JDKProxyTest

package com.rangers.proxy.jdkProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public class JDKProxyTest { public static void main(String[] args) { // 创建目标对象 IAccountService target = new AccountServiceImpl(); // 创建代理对象,传入目标对象进行初始化 IAccountService proxyService = (IAccountService) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new JdkProxy(target) ); // 亦可使用匿名类进行实现 /*(IAccountService) 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("对转账人身份校验。。"); Object result = method.invoke(target, args); System.out.println("进行日志记录。。"); return result; } });*/ // 此处执行的业务方法就是代理对象的增强过的逻辑 proxyService.transfer(); } }

注:使用JDK动态代理时需要目标类目标方法必须在实现的接口中,否则不能使用此方式进行动态打击。对于无接口的类需要实现动态代理,就要使用CGLIB方式来进行实现

b、CGLIB动态代理

概念

​ CGLIB是一个开源的第三方代码生成类库,对于无接口的类,要为其创建动态代理,就要使用CGLIB进行实现。CGLIB代理的生成原理是生成目标类的子类,子类是增强过的,就是目标类的代理类。所以,使用CGLIB生成动态代理,要求目标类必须能够被继承,即不能是final修饰的类。

​ CGLIB包的底层是通过使用一个小儿快的字节码处理框架ASM(java字节码操控框架),来转换字节码并生成新的类,通过对字节码进行增强来生成代理类。

​ 我们静态代理理解为私人律师,JDK动态代理成为代理律师,CGLIB动态代理可以理解为老父亲的儿子。老父亲是被需要增强对目标类,儿子则是用于增强父亲对代理类,事先不需要约定。父亲需要儿子增强什么,儿子就增强什么,即他们之间的关系不要接口来进行约束。

注意要点

使用CGLIB动态代理时,生成代理类的类需要实现MethodInterceptor接口及intercept()方法

public Object intercept(Object proxy,Method method,Objectp[] args,MethodProxy methodProxy) proxy:代理对象 method:代理对象的方法,即增强后的方法 args:方法参数 methodProxy:代理方法的对象

创建代理对象时使用Enhancer类

// 创建增强器 Enhancer enhancer = new Enhancer(); // 初始化增强器:将目标类指定为父类 enhancer.setSuperclass(target.class); // 初始化增强器:设置回调至本类中的intercept()方法 enhancer.setCallback(this); // 使用增强器创建代理对象进行返回 enhancer.create();

实现与解析

引入CGLIB依赖

<dependency> <groupId>cglib</groupId> <artifactId>cglib-full</artifactId> <version>2.0.2</version> </dependency>

创建目标类AccountService

package com.rangers.proxy.cglibProxy; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public class AccountService { // 转账业务 即目标方法 public void transfer() { System.out.println("进行转账操作"); } // 查询余额 即目标方法 public void getBalance() { System.out.println("查询余额操作"); } }

创建代理类AccountServiceCglibProxy实现MethodInterceptor接口,完善intercept()方法进行增强,创建生成代理对象createProxy()方法

package com.rangers.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; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public class AccountServiceCglibProxy implements MethodInterceptor { // 声明目标类的成员变量,并创建以目标类为参数的构造器,用于接收目标对象 private AccountService target; public AccountServiceCglibProxy(AccountService accountService) { this.target = accountService; } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { // 此处对目标方法进行增强 Object result = new Object(); if ("transfer".equals(method.getName())){ System.out.println("对转账人身份校验。。"); result = method.invoke(target, args); System.out.println("进行日志记录。。"); }else{ // 直接执行目标对象的目标方法 result = methodProxy.invokeSuper(target,args); } return result; } // 创建代理对象 public AccountService createProxy(){ // 创建增强器 Enhancer enhancer = new Enhancer(); // 初始化增强器:将目标类指定为父类 enhancer.setSuperclass(AccountService.class); // 初始化增强器:设置回调至本类中的intercept()方法 enhancer.setCallback(this); // 使用增强器创建代理对象 return (AccountService) enhancer.create(); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydspd.html