失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop

spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop

时间:2021-04-05 09:40:49

相关推荐

spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop

普通静态代理

代理类和真实类都需要实现同一个接口

接口

package com.fchan.layui.represent.service;/*** 静态代理demo*/public interface Subject {public void print();}

真实类

package com.fchan.layui.represent.service.impl;import com.fchan.layui.represent.service.Subject;public class RealSubject implements Subject {@Overridepublic void print() {System.out.println("被代理的对象(即真实对象)的print方法");}}

代理类

package com.fchan.layui.represent.service.impl;import com.fchan.layui.represent.service.Subject;import lombok.extern.slf4j.Slf4j;@Slf4jpublic class Proxy implements Subject {private RealSubject realSubject;public Proxy(RealSubject realSubject) {this.realSubject = realSubject;}@Overridepublic void print() {log.info("代理对象开始干活了");//被代理的对象处理业务realSubject.print();log.info("代理对象干活结束");}}

使用demo

/*** 静态代理demo*/@Testpublic void testRepresent(){Subject subject = new Proxy(new RealSubject());subject.print();}

普通的静态代理有很大的局限性,如果需要代理的目标类实现的接口方法很多.并且这些方法都需要进行扩展的话,需要写很多.所以JDK动态代理就可以很好的解决这个问题,只需要写一个具体增强实现的类实现InvocationHandler接口.就可以在invoke方法里处理被代理对象实现的所有接口方法.

JDK动态代理

代理目标类实现的接口,因为JDK动态代理是基于接口的,接口没有的方法是代理不到的.

package com.fchan.layui.represent.service;/*** 接口,代理目标类实现了这个接口*/public interface Subject {public void print();}

被代理的目标类实现了这个接口

package com.fchan.layui.represent.service.impl;import com.fchan.layui.represent.service.Subject;public class RealSubject implements Subject {@Overridepublic void print() {System.out.println("被代理的对象(即真实对象)的print方法");}}

具体去增强实现的辅助类,到这里还没去使用JDK的动态代理,这里这个增强辅助类和这个代理目标类还没有啥关系

package com.fchan.layui.represent.service;import com.fchan.layui.represent.service.impl.RealSubject;import lombok.extern.slf4j.Slf4j;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;/*** JDK的动态代理,利用InvocationHandler生成代理类*/@Slf4jpublic class JdkProxySubject implements InvocationHandler {private RealSubject realSubject;public JdkProxySubject(RealSubject realSubject) {this.realSubject = realSubject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {log.info("开始执行动态代理的逻辑,类似spring aop的@Before通知");Object result = null;try {//利用反射调用目标对象的方法result = method.invoke(realSubject,args);} catch (IllegalAccessException e) {//代理类不是真正处理的类,这里接着把异常往外面抛e.printStackTrace();throw e;} catch (IllegalArgumentException e) {e.printStackTrace();throw e;} catch (InvocationTargetException e) {e.printStackTrace();throw e;} finally {log.info("执行finally代码块,相当于springaop的@After通知");}return result;}}

/*** JDK的动态代理* 需要通过接口来实现,即目标类需要实现一个业务接口* loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载** interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口* ,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了** h:一个InvocationHandler接口,表示代理实例的调用处理程序实现的接口。每个代理实例都具有一个关联的调用处理程序。* 对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法(传入InvocationHandler接口的子类)*/@Testpublic void testJDKDynamicProxy(){RealSubject realSubject = new RealSubject();realSubject.getClass().getInterfaces();Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{Subject.class},new JdkProxySubject(new RealSubject()));//其实这里的JdkProxySubject就是实现了InvocationHandler接口的一个类,也可以直接通过匿名类的形式创建/**Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{Subject.class},new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return null;}});*/subject.print();}

那么JDK究竟帮我们生成了一个怎么样的代理类呢,我们可以在获取代理对象之前也就是Proxy.newProxyInstance之前加一行参数

//将生成的字节码保存下来System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");

Cglib动态代理,类似于jdk代理也要实现一个接口—MethodInterceptor接口

看了上面的2种代理方式后,实现cglib代理就轻车熟路啦

先创建一个代理类,实现MethodInterceptor接口

package com.fchan.layui.represent.service;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CglibDemoInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("cglib represent before");Object result = null;try {result = methodProxy.invokeSuper(o,objects);} catch (Throwable throwable) {throwable.printStackTrace();throw throwable;} finally {System.out.println("cglib represent finally");}return result;}}

然后用代理类去继承代理目标类

@Testpublic void testCglibProxy(){Enhancer enhancer = new Enhancer();//设置父类也就是需要代理增强的业务类enhancer.setSuperclass(RealSubject.class);//具体的实现了MethodInterceptor接口的子类,也就是增强目标类的代理类enhancer.setCallback(new CglibDemoInterceptor());Subject subject = (Subject) enhancer.create();subject.print();}

代理成功~

现在我们知道有JDK动态代理和Cglib动态代理了,那么这两者有啥区别呢

JDK动态代理只能代理实现了接口的类,并且只能代理接口拥有的方法Cglib动态代理不能代理父类中privatefinal的方法,因为声明了这两个关键字的这些方法对于子类是不可见的.当然对于声明了finalstatic的类也是无法代理的,因为不能被继承

.

SpringAop对JDK代理和Cglib代理的选择

如果目标对象实现了接口,则默认采用JDK动态代理如果目标对象没有实现接口,则采用Cglib进行动态代理如果目标对象实现了接口,且强制cglib代理,则使用cglib代理

SpringAop实现代理类的流程

强制进行Cglib代理

责任链模式调用demo

声明抽象类

package com.fchan.layui.chainsMethods;public abstract class Handler {private Handler successor;public Handler getSuccessor() {return successor;}public void setSuccessor(Handler successor) {this.successor = successor;}public void handlerProcess(){execution();if(null != successor){successor.handlerProcess();}}public abstract void execution();}

责任链实现demo

package com.fchan.layui.chainsMethods;public class Client {static class HandlerA extends Handler{@Overridepublic void execution() {System.out.println("HandlerA");}}static class HandlerB extends Handler{@Overridepublic void execution() {System.out.println("HandlerB");}}static class HandlerC extends Handler{@Overridepublic void execution() {System.out.println("HandlerC");}}public static void main(String[] args) {Handler handlerA = new HandlerA();Handler handlerB = new HandlerB();Handler handlerC = new HandlerC();handlerA.setSuccessor(handlerB);handlerB.setSuccessor(handlerC);handlerA.handlerProcess();}}

SpringAop中责任链的实现

实际处理的方法

package com.fchan.layui.chainsMethods.springaopChain;public abstract class ChainHandler {public void execution(Chain chain){handlerProcess();chain.proceed();}protected abstract void handlerProcess();}

责任链维护类

package com.fchan.layui.chainsMethods.springaopChain;import java.util.List;public class Chain {List<ChainHandler> chainHandlers;private int index = 0;public Chain(List<ChainHandler> chainHandlers) {this.chainHandlers = chainHandlers;}public List<ChainHandler> getChainHandlers() {return chainHandlers;}public void setChainHandlers(List<ChainHandler> chainHandlers) {this.chainHandlers = chainHandlers;}protected void proceed(){if(index >= this.getChainHandlers().size()){return;}this.getChainHandlers().get(index ++ ).execution(this);}}

调用实现,维护责任链顺序的客户端

package com.fchan.layui.chainsMethods.springaopChain;import java.util.Arrays;import java.util.List;public class ChainClient {static class ChainHandlerA extends ChainHandler{@Overrideprotected void handlerProcess() {System.out.println("chain handlerA");}}static class ChainHandlerB extends ChainHandler{@Overrideprotected void handlerProcess() {System.out.println("chain handlerB");}}static class ChainHandlerC extends ChainHandler{@Overrideprotected void handlerProcess() {System.out.println("chain handlerC");}}public static void main(String[] args) {List<ChainHandler> list = Arrays.asList(new ChainHandlerA(),new ChainHandlerB(),new ChainHandlerC());Chain chain = new Chain(list);chain.proceed();}}

spring aop的责任链调用也是如此

类名ReflectiveMethodInvocation

spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop的责任链模式调用

如果觉得《spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。