图示:
概述:
·代理模式(Proxy Pattern):是23种设计模式中的一种,属于结构型的模式。指一个对象本身不做实际的操作,而是通过其它对象来得到自己想得到的结果。
·意义:目标对象只需要关心自己的实现细节,通过代理对象来实现功能的增强,可以扩展目标对象的功能。
·体现了非常重要的编程思想:不能随便修改源码,如果需要修改源码,通过修改代理的方式来实现功能的拓展。
二、如何实现代理:
图示:
元素组成:
接口:定义行为和规范
被代理类:是目标对象
代理类:功能增强
静态代理:
创建domain对象
/**
* 学生类
*/
@Data
public class Student {
private String name;
private Integer age;
}
创建service 接口 定义规范
public interface IStudentService {
/**
* 添加学生
*/
void save();
/**
* 查询学生信息
* @param id
* @return
*/
Student query(long id);
}
创建实现类,创建被代理类
/**
* 被代理类
*/
public class StudentServiceImple implements IStudentService {
@Override
public void save() {
System.out.println("保存学生信息");
}
@Override
public Student query(long id) {
Student student=new Student();
student.setName("Colie");
student.setAge(18);
return student;
}
}
创建事务类
public class DaoTransaction {
public void before(){
System.out.println("开启事务操作");
}
public void after(){
System.out.println("关闭事务");
}
创建代理增强类对象
public class ProxyStudent implements IStudentService {
//目标类对象
private StudentServiceImple studentServiceImple;
//需要做的增强对象
private DaoTransaction daoTransaction;
//通过构造器实现目标类和增强类
public ProxyStudent(StudentServiceImple studentServiceImple,DaoTransaction daoTransaction){
this.studentServiceImple=studentServiceImple;
this.daoTransaction=daoTransaction;
}
@Override
public void save() {
//开启事务操作
daoTransaction.before();
//目标类的操纵
studentServiceImple.save();
//关闭事务操作
daoTransaction.after();
}
@Override
public Student query(long id) {
return studentServiceImple.query(id);
}
}
测试代理类对象;
public class TestStudent {
@Test
public void testStudent(){
DaoTransaction transaction=new DaoTransaction();
StudentServiceImple studentServiceImple = new StudentServiceImple();
//获取代理类对象
//包含木匾对象一级潜质通知和后置通知
ProxyStudent proxyStudent = new ProxyStudent(studentServiceImple,transaction);//构造方法
proxyStudent.save();
proxyStudent.query(1L);
}
}
实现结果:
静态代理的一些问题:
1.静态代理不利于代码的拓展,比如接口中心仪安家以后哥抽象方法时,所实现类都需要重新实现,否则报错
2.代理对象需要创造很多,这种设计很不方便和麻烦。
三:动态代理
1.概述
·概述:在不改变原有功能代码的前提下,能够动态的实现方法的增强
2.JDK动态代理
基础准备
创建Service接口
public interface IStudentService {
/**
* 添加学生
*/
void save();
/**
* 查询学生信息
* @param id
* @return
*/
Student query(long id);
// Student delete();
}
创建Service实现类:(需要代理的类)
public class StudentServiceImple implements IStudentService {
@Override
public void save() {
System.out.println("保存学生信息");
}
@Override
public Student query(long id) {
System.out.println("查询方法-----------");
Student student=new Student();
student.setName("Colie");
student.setAge(18);
return student;
}
}
增强类:
public class DaoTransaction {
public void before(){
System.out.println("开启事务操作");
}
public void after(){
System.out.println("关闭事务");
}
}
2.2实现InvocationHandler接口
实现接口
public class TransasctionHandler implements InvocationHandler {
//增强类对象
private DaoTransaction daoTransaction;
//需要代理的目标对象
private Object obj;
public TransasctionHandler(DaoTransaction daoTransaction,Object obj){
this.obj=obj;
this.daoTransaction=daoTransaction;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object responce=null;
//判断当前方法是否是save ,是才做事务操作
if ("save".equals(method.getName())) {
daoTransaction.before();
responce = method.invoke(obj, args);
daoTransaction.after();
}else {
responce=method.invoke(obj,args);
}
return responce;
}
}
分别介绍里面的参数:
proxy:代理实例。可以通过newProxyInstance创建代理实例
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
ClassLoader loader:
类加载器,直接通过需要代理的类获取就行-(StudentServiceImple.class.getClassLoader()
)
Class<?>[] interfaces:目标类所实现下的所有接口(StudentServiceImple.class.getInterfaces())
InvocationHandler h:方法拦截器,可以在里面实现方法的增强(transasctionHandler)
Method:执行目标方法的,invoke 执行
args :参数数组
测试类:
public class TestStudent {
@Test
public void testStudent(){
//增强类对象
DaoTransaction transaction=new DaoTransaction();
//目标执行类
StudentServiceImple studentServiceImple = new StudentServiceImple();
//方法拦截处理器
TransasctionHandler transasctionHandler=new TransasctionHandler(transaction,studentServiceImple);
//获取代理对象实例
IStudentService iStudentService = (IStudentService)Proxy.newProxyInstance(StudentServiceImple.class.getClassLoader(),
StudentServiceImple.class.getInterfaces(),transasctionHandler);
iStudentService.save();
iStudentService.query(1L);
}
}
2.4底层运行原理
生成代理类的字节码,原理图:
文字说明:
- 通过实现接口,获取到接口里面的所有方法
- 通过Proxy创建代理类实例
- 通过反射机制,获取到一个个的方法对象
- 调用InvocationHandler接口中的invoke方法,从而实现业务的增强
3.CGLIB动态代理
·JDK动态代理有一个前提,需要代理的类必须实现接口,如果没有实现接口,只能通过CGLB来实现,其实就是对于DK动态代理的一个补充
导包:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
准备好目标类
public interface IStudentService {
/**
* 添加学生
*/
void save(Student student);
/**
* 查询学生信息
* @param id
* @return
*/
Student query(long id);
}
public class StudentServiceImple implements IStudentService {
@Override
public void save(Student student) {
System.out.println("保存学生信息");
}
@Override
public Student query(long id) {
System.out.println("查询方法-----------");
Student student=new Student();
student.setName("Colie");
student.setAge(18);
return student;
}
}
实现方法拦截:
public class CglibIntercepter implements MethodInterceptor {
DaoTransaction transaction;
// IStudentService studentService;
public CglibIntercepter( DaoTransaction transaction){
// this.studentService=studentService;
this.transaction=transaction;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//事务增强
transaction.before();
Object res = methodProxy.invokeSuper(o, objects);
transaction.after();
return res ;
}
}
测试类:
@Test
public void testStudent() {
//得到方法拦截器
CglibIntercepter cglibIntercepter = new CglibIntercepter(new DaoTransaction());
//使用Cglib 框架生成目标类的子类(代理类)实现增强
Enhancer enhancer=new Enhancer();
//设置父类字节码
enhancer.setSuperclass(StudentServiceImple.class);
//设置拦截处理
enhancer.setCallback(cglibIntercepter);
IStudentService service=(IStudentService) enhancer.create();
service.save(new Student());
}
底层运行原理图:
·文字说明:
- 通过继承的方式去获取到目标对象的方法
- 通过传递方法拦截器MethodInterceptor实现方法拦截,在这里面做具体的增强
- 调用生成的代理类对象具体执行重写的save方法,直接去调用方法拦截器里面的intercept方法
- 前后加上了增强操作,从而实现了不修改目标代码实现业务增强
总结: