JDK动态代理CGLIB动态代理
创始人
2024-05-19 15:07:29

代理模式
是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。
房产中介代替业主卖房
在这里插入图片描述

静态代理

静态代理中代理类与被代理类都需要实现同一个接口,这就说明我们的一个静态代理类只能代理一个类,并且还要事先知道我们要代理哪个类才能写代理类,如果我们有其他类还想使用代理那就必须再写一个代理类。然而在实际开发中我们是可能是有非常多的类是需要被代理的,并且事先我们可能并不知道我们要代理哪个类。所以如果继续使用静态代理反而会增加许多的工作量,并且效率低下,代码复用率也不好。
eg:

package com.msb.test;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
public class Test1 {public static void main(String[] args) {Person person =new Person("张三");Court court=new Lawyer(person);court.doCourt();}
}
// 接口
interface Court{void doCourt();
}
// 代理类
class Lawyer implements Court{private Person person;public Lawyer(Person person) {this.person = person;}@Overridepublic void doCourt() {System.out.println("律师取证:视频证明张三当时正在旅游,不在案发现场");System.out.println("律师总结:张三不可能去杀人");person.doCourt();}
}
// 被代理的类
class Person implements Court{private String name;public Person(String name) {this.name = name;}@Overridepublic void doCourt() {System.out.println(name+"说:我没有杀人");}
}

动态代理

动态代理可以针对于一些不特定的类或者一些不特定的方法进行代理,我们可以在程序运行时动态的变化代理的规则,代理类在程序运行时才创建的代理模式成为动态代理。这种情况下,代理类并不是在Java代码中定义好的,而是在程序运行时根据我们的在Java代码中的“指示”动态生成的

动态代理两种形式:
Proxy动态代理 JDK动态代理 面向接口
cglib动态代理 第三方动态代理 面向父类

JDK动态代理

eg:
张三吃饭

package com.msb.testProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
public class Test1 {public static void main(String[] args) {Dinner dinner=new Person("张三");// 通过Porxy动态代理获得一个代理对象,在代理对象中,对某个方法进行增强
//        ClassLoader loader,被代理的对象的类加载器ClassLoader classLoader = dinner.getClass().getClassLoader();
//        Class[] interfaces,被代理对象所实现的所有接口Class[] interaces= 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 res;}};Dinner dinnerProxy =(Dinner) Proxy.newProxyInstance(classLoader,interaces,handler);//dinnerProxy.eat("包子");dinnerProxy.drink();}
}
interface Dinner{void eat(String foodName);void drink();
}
class Person implements Dinner{private String name;public Person(String name) {this.name = name;}@Overridepublic void eat(String foodName) {System.out.println(name+"正在吃"+foodName);}@Overridepublic void drink( ) {System.out.println(name+"正在喝茶");}
}
class Student implements Dinner{private String name;public Student(String name) {this.name = name;}@Overridepublic void eat(String foodName) {System.out.println(name+"正在食堂吃"+foodName);}@Overridepublic void drink( ) {System.out.println(name+"正在喝可乐");}
}

使用代理技术 获得代理对象 代替张三 增强打官司的方法

总结

1.在不修改原有代码的 或者没有办法修改原有代码的情况下 增强对象功能 使用代理对象 代替原来的对象去完成功能
进而达到拓展功能的目的
2.JDK Proxy 动态代理面向接口的动态代理 一定要有接口和实现类的存在 代理对象增强的是实现类 在实现接口的方法重写的方法
生成的代理对象只能转换成 接口的不能转换成 被代理类
代理对象只能增强接口中定义的方法 实现类中其他和接口无关的方法是无法增强的
代理对象只能读取到接口中方法上的注解 不能读取到实现类方法上的注解

缺点:
面向接口
1.必须有接口和实现类
2.增强接口中定义的方法
3.只能读取接口中方法的上注解

CGLIB动态代理弥补缺点

CGLIB动态代理(面向父类)

在这里插入图片描述

package com.msb.testCglib;
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;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
public class Test1 {@Testpublic void testCglib(){Person person =new Person();// 获取一个Person的代理对象// 1 获得一个Enhancer对象Enhancer enhancer=new Enhancer();// 2 设置父类字节码enhancer.setSuperclass(person.getClass());// 3 获取MethodIntercepter对象 用于定义增强规则MethodInterceptor methodInterceptor=new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {/*Object o,  生成之后的代理对象 personProxyMethod 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);System.out.println("饭后刷碗");}else{// 如果是其他方法 不增强运行res=methodProxy.invokeSuper(o,objects); // 子类对象方法在执行,默认会调用父类对应被重写的方法}return res;}};// 4 设置methodInterceptorenhancer.setCallback(methodInterceptor);// 5 获得代理对象Person personProxy = (Person)enhancer.create();// 6 使用代理对象完成功能personProxy.eat("包子");}
}
class Person  {public Person( ) {}public void eat(String foodName) {System.out.println("张三正在吃"+foodName);}
}

相关内容

热门资讯

世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...