可以针对一些不特定的类或者一些不特定的方法进行代理 可以在程序运行时动态变化代理规则
代理类在程序运行时才创建代理模式成为动态代理
代理类并不是在Java代码中定义好的 而是在程序运行时根据在Java代码中指示动态生成的
Proxy JDK动态代理 面向接口
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Test1 {
public static void main(String[] args) {
Dinner dinner = new Student("张三");
//通过动态代理获取一个代理对象 在代理对象中 对某个方法进行增强
//ClassLoader loader 被代理的对象的类加载器
ClassLoader classLoader = dinner.getClass().getClassLoader();
//Class<?>[] interfaces 被代理对象所实现的所有接口
Class[] interfaces =dinner.getClass().getInterfaces();
//InvocationHandler h 执行处理器对象 专门用于定义增强的规则
InvocationHandler handler = new InvocationHandler(){
//invoke 当我们让代理对象调用任何方法时 都会触发invoke方法的执行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//Object proxy 代理对象
//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 null;
}
};
Dinner dinnerProxy = (Dinner)Proxy.newProxyInstance(classLoader,interfaces,handler);
//dinnerProxy.eat("包子");
dinnerProxy.eat("包子");
}
}
interface Dinner {
void eat(String foodName);
void drink();
}
class Person implements Dinner{
private String name;
public Person(String name) {
this.name = name;
}
@Override
public void eat(String foodName) {
System.out.println(name + "正在吃" + foodName);
}
@Override
public void drink() {
}
}
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() {
System.out.println(name + "正在喝可乐");
}
}
1.在不修改原有代码的 或没有办法修改原有代码的情况下
增强对象功能 使用代理对象代替原来的对象完成功能达到拓展功能的目的
2.JDK Proxy动态代理面向接口的动态代理 一定要有接口和实现类的存在
代理对象增强的是实现类 在实现接口方法重写的方法
代理对象只能增强接口中定义的的方法 类中其他和接口无关的方法无法增强
代理对象只能读取接口中方法上的注解 不能读取到实现类方法的注解
cglib 第三方动态代理 面向父类
import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class Test1 {
@Test
public void testCglib(){
Person person = new Person();
//获取一个Person代理对象
//1.获取一个Enhancer对象
Enhancer enhancer = new Enhancer();
//2.设置父类的字节码
enhancer.setSuperclass(person.getClass());
//3.获取MethodIntercepter对象 用于定义增强规则
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("饭前洗手");
methodProxy.invokeSuper(o,objects);
System.out.println("饭后刷碗");
}else{
//如果是其他方法 不增强运行
methodProxy.invokeSuper(o,objects);//子类对象方法执行 默认调用父类对应被重写的方法
}
return res;
}
};
//4.设置回调方法
enhancer.setCallback(methodInterceptor);
//5.获得methodInterceptor
Person personProxy = (Person) enhancer.create();
//6.使用代理对象完成功能
personProxy.eat("包子");
}
class Person {
private String name;
public Person() {
}
public void eat(String foodName) {
System.out.println("张三" + "正在吃" + foodName);
}
}
}