javascript
adguard没有核心 core no_Spring 核心组件原理解析
Spring 的核心
任何實際的應用程序都是由很多組件組成的,每個組件負責整個應用功能的一部分,這些組件需要與其他的應用元素進行協調以完成自己的任務。當應用程序運行時,需要以某種方式創建并引入這些組件。Spring Framework 總共有十幾個組件,但真正核心的組件只有三個:Spring Core,Spring Context 和 Spring Bean,它們奠定了 Spring 的基礎并撐起了 Spring 的框架結構。Spring 的其它功能特性例如 Web、AOP、JDBC 等都是在其基礎上發展實現的。Spring之中最重要的當屬Bean了,Spring實際上就是面向Bean的編程,Bean對于Spring的意義就好比Object對于OOP的意義一樣。那么,三個核心組件之間是如何協同工作的呢?如果把Bean比作一場演出中的演員,那么Context就是這場演出的舞臺,Core就是演出的道具,至于演出的節目,就是Spring的一系列特色功能了。
我們知道Bean包裹的是Object,而Object中必然有數據,Context就是給這些數據提供生存環境,發現每個Bean之間的關系,為他們建立并維護好這種關系。這樣來說,Context就是一個Bean關系的集合,這個關系集合就是我們所說的IOC容器。那么Core又有什么作用呢?Core就是發現、建立和維護每個Bean之間的關系所需的一系列工具,就是我們經常說的Util。
Bean 組件
Bean組件在Spring的org.springframework.beans包下,主要完成了Bean的創建、Bean的定義以及Bean的解析三件事。SpringBean的創建是典型的工廠模式,其工廠的繼承層次關系如圖所示:
Spring 使用工廠模式來管理程序中使用的對象(Bean),Bean 工廠最上層的接口為 BeanFactory,簡單來看,工廠就是根據需要返回相應的 Bean 實例。public interface BeanFactory { //... Object getBean(String name);}在工廠模式中,在工廠的實現類中生成 Bean 返回給調用客戶端,這就要求客戶端提供生成自己所需類實例的工廠類,增加客戶負擔。Spring 結合控制反轉和依賴注入為客戶端提供所需的實例,簡化了客戶端的操作。具體的實現方式大致如下。public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { /** Map of bean definition objects, keyed by bean name */ private final Map beanDefinitionMap = new ConcurrentHashMap; public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition){ //... }}beanDefinitionMap 作為具體的 Bean 容器,Spring 創建的對象實例保存其中。客戶端需要時,使用工廠的 getBean 方法去試圖得到相應的實例,如果實例已存在,則返回該實例;如果實例不存在,則首先產生相應實例并通過 registerBeanDefinition 方法將其保存在 beanDefinitionMap 中(Lazy Initialization),然后返回該實例給客戶端。Spring Bean 工廠的繼承關系beanDefinitionMap 并不直接保存實例本身,而是將實例封裝在 BeanDefinition 對象后進行保存。BeanDefinition 包含了實例的所有信息,其簡化版的定義如下。public class BeanDefinition { private Object bean; private Class> beanClass; private String beanClassName; // Bean 屬性字段的初始化值 private BeanPropertyValues beanPropertyValues; //...}Spring Bean 工廠生產 Bean 時
假設我們已經完成了步驟 1) 的操作,之后的過程用代碼表述如下所示。
Context 組件
前面說到,Context組件的作用是給Spring提供一個運行時的環境,用以保存各個對象的狀態,我們來看一下與Context相關的類結構圖。
從圖中可以看出,Context類結構的頂級父類是ApplicationContext,它除了能標識一個應用環境的基本信息以外,還繼承了5個接口,這5個接口主要是擴展了Context的功能。ApplicationContext的子類主要包含兩個方向,圖中已作說明。再往下就是構建Context的文件類型,接著就是訪問Context的方式。
一般地,傳統的程序設計中,無論是使用工廠創建實例,或是直接創建實例,實例調用者都要先主動創建實例,而后才能使用。控制反轉(Inverse of Control) 將實例的創建過程交由容器實現,調用者將控制權交出,是所謂控制反轉。依賴注入(Dependence Injection) 在控制反轉的基礎上更進一步。如果沒有依賴注入,容器創建實例并保存后,調用者需要使用 getBean(String beanName) 才能獲取到實例。使用依賴注入時,容器會將 Bean 實例自動注入到完成相應配置的調用者,供其進一步使用。Context 組件借助上述的控制反轉和依賴注入,協助實現了 Spring 的 Ioc 容器。下面我們以一個 Service 類作為所需的 Bean 實例進行說明。實際應用中,我們會需要 Spring 管理很多 Bean 實例。public class SampleService { private String service; public String getService() { return service; } public void setService(String service) { this.service= service; }}在程序運行過程中,需要一個 SampleService ,我們不讓調用者 new 一個實例,而是在配置文件中表明該 SampleService 的實例交由 Spring 容器進行管理,并指定其初始化參數。配置文件即資源,其內容如下。<?xml version="1.0" encoding="UTF-8"?><beans> <bean name="sampleService " class="com.service.SampleService "> <property name="service" value="This is a service">property> bean>beans>Spring Core 組件提供 ResourceLoader 接口,便于讀入 xml 文件或其他資源文件。其核心功能代碼應該提供如下方法。public class ResourceLoader { public Resource getResource(String location){ URL resource = this.getClass().getClassLoader().getResource(location); return new UrlResource(resource); }}// UrlResource 的功能代碼public class UrlResource implements Resource { private final URL url; public UrlResource(URL url){ this.url = url; } @Override public InputStream getInputStream() throws IOException { URLConnection urlConnection = url.openConnection(); urlConnection.connect(); return urlConnection.getInputStream(); }}即加載資源文件,并以數據流的形式返回。Context 根據資源中的定義,生成相應的 bean 并保存在容器中,bean 的名字是 sampleService ,供程序進一步使用。這樣就完成了控制反轉的工作。接下來就需要把 sampleService 注入到需要使用它的地方,亦即完成依賴注入操作。現在假設 SampleController 中使用 SampleService 的對象,Spring 提供三種依賴注入的方式,構造器注入、setter 注入和注解注入。public class SampleController { /** * 3\. 注解注入 **/ /* @Autowired */ private SampleService sampleService; /** * 1\. 構造器注入 **/ public SampleController(SampleService sampleService){ this.sampleService = sampleService; } //無參構造函數 public SampleController(){} // 類的核心功能 public void process(){ System.out.println(sampleService.getService()); } /** * 2\. setter 注入 **/ /*public void setService(SampleService service) { this.service= service; }*/}三種注入方式在配置文件中對應不同的配置方式,在前面 xml 文件的基礎上,我們可以分別實現這三種注入方式。需要注意的是,這里 SampleController 也是使用 Spring 的 Ioc 容器生成管理的。<?xml version="1.0" encoding="UTF-8"?><beans> <bean name="sampleService " class="com.service.SampleService "> <property name="service" value="This is a service">property> bean> <bean name="sampleContorller" class="com.controller.SampleContorller"> <constructor-arg index="0" ref="sampleService">constructor-arg> bean> bean>-->beans>Core組件
Core組件一個重要的組成部分就是定義了資源的訪問方式。Core組價把所有的資源都抽象成一個接口,這樣,對于資源使用者來說,不需要考慮文件的類型。對資源提供者來說,也不需要考慮如何將資源包裝起來交給別人使用(Core組件內所有的資源都可以通過InputStream類來獲取)。另外,Core組件內資源的加載都是由ResourceLoader接口完成的,只要實現這個接口就可以加載所有的資源。
那么,Context和Resource是如何建立關系的呢?通過前面Context的介紹我們知道,Context組件里面的類或者接口最終都實現了ResourcePatternResolver接口,ResourcePatternResolver接口的作用就是加載、解析和描述資源。這個接口相當于Resource里面的一個接頭人,它把Resource里的資源加載、解析和定義整合到一起,便于其他組件使用。
前面介紹了三大核心組件的結構與相互關系,那么,這三大組件是如何讓Spring完成諸如IOC和AOP等各種功能的呢?敬請期待下一篇文章!
最后留一個問題:Spring 為什么能夠長盛不衰?
看完有收獲,不妨點個“在看”呀總結
以上是生活随笔為你收集整理的adguard没有核心 core no_Spring 核心组件原理解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 进制转换c++代码_跟小黑学漏洞利用开发
- 下一篇: springboot controlle