spring原始碼解讀-aop
aop是指面向切面程式設計,ProxyFactoryBean是spring aop的底層實現與源頭,為什麼這麼說呢?首先我們看一段配置:
1、target是目標物件,需要對其進行切面增強
2、proxyInterfaces是指代理物件所實現的介面
3、interceptorNames:是指通知器(Advisor)列表,通知器中包含了通知advice與切點pointcut
概括一下,ProxyFactoryBean的作用是:
針對目標物件來建立代理物件,將對目標物件方法的呼叫轉到對相應代理物件方法的呼叫,並且可以在代理物件方法呼叫前後執行與之匹配的各個通知器中定義好的方法
spring透過兩種方式來建立目標代理物件:
1、JDK動態代理
2、CGLIB
在spring中這兩種代理方式都實現了AopProxy介面去,如下圖所示:
spring中AopProxyFactory是一個介面,介面中只有一個方法createAopProxy,這個介面是有一個實現類DefaultAopProxyFactory,用來建立AopProxy物件,如下圖所示:
下面我們比較並實現以下兩種代理方式:
首先明確以下我們常用的代理模式有什麼問題,在我們經常使用的代理模式中,真實物件必須是事先存在的,並將其作為代理物件的內部屬性,在使用時,一個真實角色必須對應一個dialing角色,如果大量使用會導致類的急劇膨脹,java的動態代理類就可以解決這個問題。
JDK動態代理
java動態代理類位於java.lang.reflect包下,一般主要涉及到兩個類:
1、Interface InvocationHandler:該介面中只定義了一個方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
第一個引數proxy是指代理類,method是被代理的方法,args為該方法的引數陣列
2、Proxy:該類為動態代理類,其主要方法如下
public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h) throws IllegalArgumentException
該方法返回代理類的一個例項,返回後的代理類可以被當作代理類使用
JDK動態代理實現步驟:
1、建立一個實現介面InvocationHandler的類(DynamicSubject),它必須實現invoke方法
public class DynamicSubject implements InvocationHandler { private Object sub; public DynamicSubject(Object sub) { this.sub = sub; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before calling:" + method); method.invoke(sub, args); System.out.println(args == null); System.out.println("after calling:" + method); return null; } }
2、建立被代理的類(RealSubject)以及介面(Subject)
public interface Subject { public void request(); }
public class RealSubject implements Subject { public void request() { System.out.println("from real subject"); } }
3、透過Proxy的靜態方法newProxyInstance建立一個代理
public class Client { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); InvocationHandler handler = new DynamicSubject(realSubject); Class> classType = handler.getClass(); Subject subject = (Subject) Proxy.newProxyInstance(classType.getClassLoader(), realSubject.getClass().getInterfaces(), handler); subject.request(); System.out.println(subject.getClass()); } }
如果目標類並未實現介面,那麼Spring就會使用CGLIB庫為其建立代理,如下demo運用了CGLIB實現代理
1、建立被代理類Person
public class Person { public void study() { System.out.println("study"); } }
2、建立CglibProxy實現代理
public class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class> clazz) { enhancer.setSuperclass(clazz); enhancer.setCallback(this); Object object = enhancer.create(); return object; } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println(o.getClass().getName() + "." + method.getName()); //執行父類對應方法 final Object result = methodProxy.invokeSuper(o, objects); System.out.println("執行結束"); return result; } public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); Person person = (Person) proxy.getProxy(Person.class); System.out.println(person.getClass().getName()); person.study(); } }
下面我們來比較一下,兩種代理方法的區別
1、JDK動態代理只能對實現了介面的類生成代理,而不能針對類
2、CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法
3、在spring中如果bean實現了介面spring用JDK動態代理,如果bean沒有實現介面,spring使用CGLIB實現代理
4、CGLIb不能對宣告為final的方法進行dialing,因為CGLib原理是動態生成被代理類的子類
5、JDK動態代理透過反射的newInstance方法產生代理類的物件
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2618/viewspace-2803760/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深入淺出解讀 Spring 原始碼:IOC/AOP 篇Spring原始碼
- Spring AOP 原始碼解析Spring原始碼
- Spring:原始碼解讀Spring IOC原理Spring原始碼
- Spring AOP之原始碼分析Spring原始碼
- Spring原始碼剖析6:Spring AOP概述Spring原始碼
- 5.2 Spring5原始碼--Spring AOP原始碼分析二Spring原始碼
- 5.1 Spring5原始碼--Spring AOP原始碼分析一Spring原始碼
- Spring事務原始碼解讀Spring原始碼
- Spring原始碼剖析7:AOP實現原理詳解Spring原始碼
- Spring AOP 原理原始碼深度剖析Spring原始碼
- 5.2 spring5原始碼--spring AOP原始碼分析三---切面原始碼分析Spring原始碼
- spring-MVC原始碼解讀(一)SpringMVC原始碼
- Spring中AOP相關原始碼解析Spring原始碼
- 《四 spring原始碼》利用TransactionManager手寫spring的aopSpring原始碼
- 5.2 spring5原始碼--spring AOP原始碼分析二--切面的配置方式Spring原始碼
- Spring原始碼解讀之BeanFactoryPostProcessor的處理Spring原始碼Bean
- 原始碼解析Spring AOP的載入與生效原始碼Spring
- Spring原始碼分析之AOP從解析到呼叫Spring原始碼
- Spring AOP高階應用與原始碼剖析Spring原始碼
- Spring原始碼系列(四)--spring-aop是如何設計的Spring原始碼
- 5.3 Spring5原始碼--Spring AOP使用介面方式實現Spring原始碼
- Spring5.0原始碼學習系列之Spring AOP簡述Spring原始碼
- Spring AOP 詳解Spring
- 《spring原始碼解讀》 - IoC 之解析 import 標籤Spring原始碼Import
- 從原始碼入手,一文帶你讀懂Spring AOP面向切面程式設計原始碼Spring程式設計
- 按照自己的思路研究Spring AOP原始碼【2】Spring原始碼
- Spring中AOP相關的API及原始碼解析SpringAPI原始碼
- 淺嘗Spring註解開發_AOP原理及完整過程分析(原始碼)Spring原始碼
- Spring原理與原始碼分析系列(六)- Spring AOP入門與概述Spring原始碼
- Spring原始碼閱讀——ClassPathXmlApplicationContext(二)Spring原始碼XMLAPPContext
- Spring原始碼解讀(1)-IOC容器BeanDefinition的載入Spring原始碼Bean
- Spring Boot Transactional註解原始碼閱讀筆記(一)Spring Boot原始碼筆記
- Spring Boot Transactional註解原始碼閱讀筆記(二)Spring Boot原始碼筆記
- PostgreSQL 原始碼解讀(3)- 如何閱讀原始碼SQL原始碼
- Spring Aop 詳解二Spring
- Spring Aop 詳解一Spring
- 按照自己的思路去研究Spring AOP原始碼【1】Spring原始碼
- FairyGUI原始碼解讀AIGUI原始碼