设计模式-动态代理
概述:在不改变原有功能代码的前提下,能够动态的实现方法的增强
前期准备:
辅助jar包
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!--<scope>test</scope>-->
</dependency>
业务类
import com.hdx.cglib.dto.Student;
public interface IStudentService {
public void save(Student student);
public Student query(Long id);
}
public class StudentServiceImpl implements IStudentService {
public void save(Student student) {
System.out.println("保存学生信息");
}
public Student query(Long id) {
System.out.println("查询操作");
Student student = new Student();
student.setName("sy");
student. setAge (18);
return student;
}
}
import lombok.Data;
@Data
public class Student {
private String name;
private int age;
}
一:jdk动态代理
1.1实现InvocationHandler接
InvocationHandler 接口,用来做方法拦截
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicHandler implements InvocationHandler {
@Override
public Object invoke(Object oProxy, Method method, Object[] objects) throws Throwable {
return null;
}
}
分别介绍里面的参数
oProxy:代理实例,可以通过newProxylnstance创建代理实例。
Method:执行目标方法的,invoke 方法执行
oargs:参数数组
1.2:动态代理类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * */ public class DynamicHandler implements InvocationHandler { //动态代理类需要被代理的实例 private Object bean; public DynamicHandler(Object bean) { this.bean = bean; } @Override public Object invoke(Object oProxy, Method method, Object[] objects) throws Throwable { // 执行前置业务 System.out.println("执行前置业务"); //此处就是执行被代理类的方法 Object invoke = method.invoke(bean, objects); // 执行后置业务 System.out.println("执行后置业务"); return invoke; } }
1.3:测试
import com.hdx.cglib.dto.Student; import com.hdx.cglib.service.IStudentService; import com.hdx.cglib.service.StudentServiceImpl; import org.junit.jupiter.api.Test; import java.lang.reflect.Proxy; class DynamicHandlerTest { @Test void invoke() { // 目标执行类 IStudentService service = new StudentServiceImpl(); // 方法拦截处理类 DynamicHandler dynamicHandler = new DynamicHandler(service); // 获取代理实例对象 IStudentService proxyBean = (IStudentService) Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces(), dynamicHandler); Student student = proxyBean.query(88l); } }
分别介绍里面的参数
Proxy:代理实例,可以通过newProxylnstance创建代理实例
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
ClassLoader类加载器,直接通过需要代理的类获取就行
Class[]:目标类所实现的所有接口
lnvocationHandler:方法拦截处理器,可以在里面实现方法的增强
Method:执行目标方法的,invoke 方法执行
args:参数数组
二:cglib代理
2.1:引入cglib依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
2.2:代理了拦截类
import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * * cglib动态代理类 */ public class CglibInterceptor implements MethodInterceptor { @Override public Object intercept(Object bean, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { // 执行前置增强业务 System.out.println("befor"); //执行代理的目标类方法 Object result = methodProxy.invokeSuper(bean, objects); // 执行后置增强业务 System.out.println("after"); return result; } }
2.3:代理测试类
import com.hdx.cglib.dto.Student; import com.hdx.cglib.service.IStudentService; import com.hdx.cglib.service.StudentServiceImpl; import net.sf.cglib.core.DebuggingClassWriter; import net.sf.cglib.proxy.Enhancer; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class CglibInterceptorTest { @Test void intercept() { // 生成目标代理类 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:\\workspace\\kafkaWork\\hkafka\\src\\main\\resources\\static"); // 得到方法拦截器 CglibInterceptor cglibInterceptor = new CglibInterceptor(); //使用CGLIB框架生成目标类的子类(代理类)实现增强 Enhancer enhancer = new Enhancer(); // 设置父类字节码 enhancer.setSuperclass(StudentServiceImpl.class); // 设置拦截处理器 enhancer.setCallback(cglibInterceptor); IStudentService studentService = (IStudentService) enhancer.create(); studentService.save(new Student()); } }
2.4:实现原理
。通过继承的方式去获取到目标对象的方法
。通过传递方法拦截器Methodlnterceptor实现方法拦截,在这里面做具体的增强
。调用生成的代理类对象具体执行重写的save方法,直接去调用方法拦截器里面的intercept 方法
。前后加上了增强操作,从而实现了不修改目标代码实现业务增强
三:区别