代理模式是通过代理对象来访问真实对象,通过建立一个对象代理类,由代理对象控制原对象的引用,从而实现对真实对象的操作。
创建接口
package com.lq.proxy.v1;
/**
* @author lq
* @PACKAGE_NAME: com.lq.proxy.v1
* @CLASS_NAME: Court
* @date 2022/11/16 21:08
* @Description:
*/
public interface Court {
void doCourt();
}
创建被代理类
/**
* @author lq
* @PACKAGE_NAME: com.lq.proxy.v1
* @CLASS_NAME: Person
* @date 2022/11/16 21:09
* @Description: 人物类 被代理者
*/
public class Person implements Court {
private String name;
public Person(String name) {
this.name = name;
}
@Override
public void doCourt() {
System.out.println(name + "说:我没有犯罪!");
}
}
创建静态代理类
package com.lq.proxy.v1;
/**
* @author lq
* @PACKAGE_NAME: com.lq.proxy.v1
* @CLASS_NAME: Lawyer
* @date 2022/11/16 21:08
* @Description: 律师 代理者
*/
public class Lawyer implements Court{
//被代理类
private Person person;
public Lawyer(Person person) {
this.person = person;
}
@Override
public void doCourt() {
person.doCourt();
System.out.println("律师取证:视频证明张三当时正在旅游,不在案发现场!");
System.out.println("律师总结:张三不可能犯罪!");
}
}
测试
package com.lq.proxy.v1;
/**
* @author lq
* @PACKAGE_NAME: com.lq.proxy.v1
* @CLASS_NAME: Main
* @date 2022/11/16 21:11
* @Description:
*/
public class Main {
public static void main(String[] args) {
Person person =new Person("张三");
Court court=new Lawyer(person);
court.doCourt();
}
}
结果:
张三说:我没有犯罪!
律师取证:视频证明张三当时正在旅游,不在案发现场!
律师总结:张三不可能犯罪!
动态代理可以针对于一些不特定的类或者一些不特定的方法进行代理,我们可以在程序运行时动态的变化代理的规则,代理类在程序运行时才创建的代理模式成为动态代理。这种情况下,代理类并不是在Java代码中定义好的,而是在程序运行时根据我们的在Java代码中的“指示”动态生成的。
代理类型 | 使用场景 |
---|---|
JDK动态代理 | 面向接口 |
cglib动态代理 | 面向父类 |
声明接口
package com.lq.proxy.v2;
/**
* @author lq
* @PACKAGE_NAME: com.lq.proxy.v2
* @CLASS_NAME: Dinner
* @date 2022/11/16 21:13
* @Description:
*/
public interface Dinner {
/**
* 吃什么东西
* @param foodName
*/
void eat(String foodName);
/**
* 喝什么东西
* @param drinkName
*/
void drink(String drinkName);
}
创建实现类
package com.lq.proxy.v2;
/**
* @author lq
* @PACKAGE_NAME: com.lq.proxy.v2
* @CLASS_NAME: Student
* @date 2022/11/16 21:14
* @Description:
*/
public class Student implements Dinner {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public void eat(String foodName) {
System.out.println(name + ":正在吃-->" + foodName);
}
@Override
public void drink(String drinkName) {
System.out.println(name + "正在喝-->" + drinkName);
}
}
JDK代理实现
package com.lq.proxy.v2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author lq
* @PACKAGE_NAME: com.lq.proxy.v2
* @CLASS_NAME: Main
* @date 2022/11/16 21:16
* @Description: Proxy 动态代理 JDK动态代理 面向接口
*/
public class Main {
public static void main(String[] args) {
Dinner dinner = new Student("张三");
// 通过Porxy动态代理获得一个代理对象,在代理对象中,对某个方法进行增强
// ClassLoader loader,被代理的对象的类加载器
ClassLoader classLoader = dinner.getClass().getClassLoader();
// Class>[] interfaces,被代理对象所实现的所有接口
Class[] interaces = dinner.getClass().getInterfaces();
// InvocationHandler h,执行处理器对象,专门用于定义增强的规则
InvocationHandler handler = new InvocationHandler() {
// invoke 当我们让代理对象调用任何方法时,都会触发invoke方法的执行
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Object proxy, 生成后的代理类 及下边的 dinnerProxy
// Method method,被代理的方法
//Object[] args,被代理方法运行时的实参
Object res = null;
if (method.getName().equals("eat")) {
System.out.println("饭前洗手");
// 让原有的eat的方法去运行
res = method.invoke(dinner, args);
System.out.println("饭后刷碗");
} else {
// 如果是其他方法,那么正常执行就可以了
res = method.invoke(dinner, args);
}
return res;
}
};
Dinner dinnerProxy = (Dinner) Proxy.newProxyInstance(classLoader, interaces, handler);
dinnerProxy.eat("包子");
dinnerProxy.drink("可乐");
}
}
结果
饭前洗手
张三:正在吃-->包子
饭后刷碗
张三正在喝-->可乐
创建目标类
package com.lq.proxy.v3;
/**
* @author lq
* @PACKAGE_NAME: com.lq.proxy.v3
* @CLASS_NAME: Person
* @date 2022/11/16 21:28
* @Description:
*/
public class Person {
public Person() {
}
public void eat(String foodName) {
System.out.println("正在吃 -->" + foodName);
}
}
CGLIB动态代理实现
package com.lq.proxy.v3;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @author lq
* @PACKAGE_NAME: com.lq.proxy.v3
* @CLASS_NAME: Main
* @date 2022/11/16 21:29
* @Description:
*/
public class Main {
public static void main(String[] args) {
Person person = new Person();
// 获取一个Person的代理对象
// 1 获得一个Enhancer对象
Enhancer enhancer = new Enhancer();
// 2 设置父类字节码
enhancer.setSuperclass(person.getClass());
// 3 获取 MethodInterceptor 对象 用于定义增强规则
MethodInterceptor methodInterceptor = new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//Object o, 生成之后的代理对象 personProxy
//Method method, 父类中原本要执行的方法 Person >>> eat()
//Object[] objects, 方法在调用时传入的实参数组
//MethodProxy methodProxy 子类中重写父类的方法 personProxy >>> eat()
Object res = null;
if (method.getName().equals("eat")) {
// 如果是eat方法 则增强并运行
System.out.println("饭前洗手");
res = methodProxy.invokeSuper(o, objects);
//res = method.invoke(person,objects);
System.out.println("饭后刷碗");
} else {
// 如果是其他方法 不增强运行
res = methodProxy.invokeSuper(o, objects); // 子类对象方法在执行,默认会调用父类对应被重写的方法
}
return res;
}
};
// 4 设置 methodInterceptor 回调
enhancer.setCallback(methodInterceptor);
// 5 获得代理对象
Person personProxy = (Person) enhancer.create();
// 6 使用代理对象完成功能
personProxy.eat("包子");
}
}
结果
饭前洗手
正在吃 -->包子
饭后刷碗