spring初学入门(3)——代理设计模式(了解AOP必学)bai

it2025-04-21  14

代理模式——AOP的核心

想要先学好spring框架的第二大难点AOP(面向切面编程),就要先了解什么是代理模式,静态代理和动态代理是什么,JDK动态代理和CGLIB动态代理的区别是什么

代理设计模式

代理模式是Java常见的设计模式之一。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。 为什么要采用这种间接的形式来调用对象呢?

1.因为客户端不想直接访问实际的对象,或者访问实际的对象存在困难,因此通过一个代理对象来完成间接的访问。

2.不改变原程序代码的前提下,对功能进行扩充。通过代理模式,我们可以很方便的给代码添加日志记录,事务控制,权限控制等一系列功能。

1.静态代理

话不多说上代码 通过黄牛购买火车票例子

//定义一个车票接口,作为其他类的父类 public interface Ticket { void buyTicket(); } /** * 12306 直接购买 */ public class By12306TicketImpl implements Ticket{ @Override public void buyTicket() { System.out.println("12306 买票"); } } /** * 通过黄牛购买 */ public class HuangNiuTicketImpl implements Ticket { private Ticket ticket; public void setTicket(Ticket ticket) { this.ticket = ticket; } @Override public void buyTicket() { System.out.println("黄牛开始买票"); if (ticket!=null){ ticket.buyTicket(); } System.out.println("黄牛买票成功"); } }

测试

public class Test { public static void main(String[] args) { // 自己买票 Ticket ticket = new By12306TicketImpl(); ticket.buyTicket(); // 通过黄牛买票,最终票的来源还是12306 HuangNiuTicketImpl huangNiu = new HuangNiuTicketImpl(); huangNiu.setTicket(ticket); huangNiu.buyTicket(); } }

2.JDK动态代理

java中动态代理主要有JDK和CGLIB两种方式。

区别主要是jdk是代理接口,而cglib是代理类。

JDK动态代理步骤:

1.实现InvocationHandler接口

2.创造代理对象

3.通过反射执行目标对象方法

/** * 只能代理 实现接口的对象 */ public class JDKProxy implements InvocationHandler { private Object targetObject; /** * 产生两个代理对象 * @param object * @return */ public Object getProxyInstance(Object object) { this.targetObject = object; Class<?> classes = targetObject.getClass(); //ClassLoader loader,指定当前目标对象使用类加载器,我们知道获取加载器的写法是固定的 //Class<?>[ ] interfaces,目标对象实现的接口的类型,使用泛型方式确认类型,我们知道要想知道一个类是否实现某个接口,可以使用 Object.getClass().getInterfaces() ,这个方法是获取类是否实现接口,如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象。 //InvocationHandler h,事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入 return Proxy.newProxyInstance(classes.getClassLoader(),classes.getInterfaces(),this); } /** * 当目标对象执行对应的方法时,这个方法会被调用,对目标方法进行增强 * @param proxy * @param method * @param args * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("动态代理开始工作"); // 返回值为方法 执行返回的结果,若为void 则返回null Object result = method.invoke(targetObject,args); System.out.println("动态代理工作完成"); return result; } }

测试

public class JDkProxyTest { public static void main(String[] args) { //12306 目标对象 final Ticket by12306 = new By12306TicketImpl(); //创建一个代理对象 //ClassLoader loader,指定当前目标对象使用类加载器,我们知道获取加载器的写法是固定的 //Class<?>[ ] interfaces,目标对象实现的接口的类型,使用泛型方式确认类型,我们知道要想知道一个类是否实现某个接口,可以使用 Object.getClass().getInterfaces() ,这个方法是获取类是否实现接口,如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象。 //InvocationHandler h,事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入 Ticket proxyticket = (Ticket) Proxy.newProxyInstance(by12306.getClass().getClassLoader(), by12306.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理对象开始调用目标对象"); //让目标 对象执行方法 并且获取返回结果 Object result = method.invoke(by12306, args); System.out.println("代理对象结束调用目标对象"); return result; } }); proxyticket.buyTicket(); } }

结果

代理对象开始调用目标对象 12306 出票: 火车票:郑州---->南京 代理对象结束调用目标对象

3.CGLIB动态代理

关于CGLIB动态代理只需要李姐 CGLIB和JDK动态代理的区别即可 代码看看就行,眼熟一下,和JDK动态代理的步骤差不多

CGLIB和JDK动态代理的区别? 1.jdk 实现代理目标对象 必须实现接口 cglib 是根据目标对象/目标类生成代理类的字节码文件 ,不要求必须实现接口 2.在生成代理类的效率上 cglib 效率差 因为要生成字节码文件 jdk 效率高 3.在代理类方法调用执行上说 cglib 直接执行class 文件的方法 效率高 jkd 通过反射实现 效率低

/** * cglib 创建代理代理对象的工具类 */ public class CglibProxy implements MethodInterceptor { /** * 创建代理对象 * @param superclass * @return */ public Object createProxy(Class superclass){ Enhancer enhancer = new Enhancer(); // 传递目标类 cglib 的原理是生成的代理类是 目标类的子类 enhancer.setSuperclass(superclass); enhancer.setCallback(this); // 创建 代理对象 return enhancer.create(); } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("cglib 代理开始调用 目标对象"); // 让目标 对象执行 // o 目标对象 // objects 目标对象执行方法需要的惨呼 Object result = methodProxy.invokeSuper(o,objects); System.out.println("cglib-result:"+result); System.out.println("cglib 代理结束调用 目标对象"); return result; } } public class CglibProxyTest2 { public static void main(String[] args) { // 生成动态代理 的工具类 CglibProxy cglibProxy = new CglibProxy(); // 12306 代理对象 TicketBy12306Impl ticketBy12306Proxy = (TicketBy12306Impl) cglibProxy.createProxy(TicketBy12306Impl.class); ticketBy12306Proxy.bubTicket(); System.out.println("*********************"); // 第二个代理对象 RealSubject realSubjectProxy = (RealSubject) cglibProxy.createProxy(RealSubject.class); realSubjectProxy.action(); } }
最新回复(0)