摘要:目前建議使用與。入?yún)⑹钱?dāng)前正在處理的,是當(dāng)前的配置名,返回的對(duì)象為處理后的。如果,則將放入容器的緩存池中,并返回。和這兩個(gè)接口,一般稱它們的實(shí)現(xiàn)類為后處理器。體系結(jié)構(gòu)讓容器擁有了發(fā)布應(yīng)用上下文事件的功能,包括容器啟動(dòng)事件關(guān)閉事件等。
點(diǎn)擊進(jìn)入我的博客 1 如何理解IoC 1.1 依然是KFC的案例
interface Burger { int getPrice(); } interface Drink { int getPrice(); } class ZingerBurger implements Burger { public int getPrice() { return 10; } } class PepsiCola implements Drink { public int getPrice() { return 5; } } /** * 香辣雞腿堡套餐 */ class ZingerBurgerCombo { private Burger burger = new ZingerBurger(); private Drink drink = new PepsiCola(); public int getPrice() { return burger.getPrice() + drink.getPrice(); } }
上述案例中我們實(shí)現(xiàn)了一個(gè)香辣雞腿堡套餐,在ZingerBurgerCombo中,我們發(fā)現(xiàn)套餐與漢堡、套餐與飲品產(chǎn)生了直接的耦合。要知道肯德基中的套餐是非常多的,這樣需要建立大量不同套餐的類;而且如果該套餐中的百事可樂(lè)如果需要換成其他飲品的話,是不容易改變的。
class KFCCombo { private Burger burger; private Drink drink; public KFCCombo(Burger burger, Drink drink) { this.burger = burger; this.drink = drink; } } class KFCWaiter { public KFCCombo getZingerBurgerCombo() { return new KFCCombo(new ZingerBurger(), new PepsiCola()); } // else combo… }
為了防止套餐和漢堡、飲品的耦合,我們統(tǒng)一用KFCCombo來(lái)表示所有的套餐組合,引入了一個(gè)新的類KFCWaiter,讓她負(fù)責(zé)所有套餐的裝配。
1.2 控制反轉(zhuǎn)與依賴注入IoC的字面意思是控制反轉(zhuǎn),它包括兩部分的內(nèi)容:
控制:在上述案例中,控制就是選擇套餐中漢堡和飲品的控制權(quán)。
反轉(zhuǎn):反轉(zhuǎn)就是把該控制權(quán)從套餐本身中移除,放到專門的服務(wù)員手中。
對(duì)于Spring來(lái)說(shuō),我們通過(guò)Spring容器管理來(lái)管理和控制Bean的裝配。
由于IoC這個(gè)重要的概念比較晦澀隱諱,Martin Fowler提出了DI(Dependency Injection,依賴注入)的概念用以代替IoC,即讓調(diào)用類對(duì)某一接口實(shí)現(xiàn)類的依賴關(guān)系由第三方(容器或協(xié)作類)注入,以移除調(diào)用類對(duì)某一接口實(shí)現(xiàn)類的依賴。
Spring就是一個(gè)容器,它通過(guò)配置文件或注解描述類和類之間的依賴關(guān)系,自動(dòng)完成類的初始化和依賴注入的工作。讓開(kāi)發(fā)著可以從這些底層實(shí)現(xiàn)類的實(shí)例化、依賴關(guān)系裝配等工作中解脫出來(lái),專注于更有意義的業(yè)務(wù)邏輯開(kāi)發(fā)。
2 IoC的類型從注入方法上看,IoC可以分為:構(gòu)造函數(shù)注入、屬性注入、接口注入
class KFCCombo { private Burger burger; private Drink drink; // 在此注入對(duì)應(yīng)的內(nèi)容 public KFCCombo(Burger burger, Drink drink) { this.burger = burger; this.drink = drink; } }
class KFCCombo { private Burger burger; private Drink drink; // 在此注入對(duì)應(yīng)的內(nèi)容 public void setBurger(Burger burger) { this.burger = burger; } // 在此注入對(duì)應(yīng)的內(nèi)容 public void setDrink(Drink drink) { this.drink = drink; } }
interface InjectFood { void injectBurger(Burger burger); void injectDrink(Drink drink); } class KFCCombo implements InjectFood { private Burger burger; private Drink drink; // 在此注入對(duì)應(yīng)的內(nèi)容 public void injectBurger(Burger burger) { this.burger = burger; } // 在此注入對(duì)應(yīng)的內(nèi)容 public void injectDrink(Drink drink) { this.drink = drink; } }
接口注入和屬性注入并無(wú)本質(zhì)的區(qū)別,而且還增加了一個(gè)額外的接口導(dǎo)致代碼增加,因此不推薦該方式。
3 資源訪問(wèn)JDK提供的訪問(wèn)資源的類(如java.net.URL、File等)并不能很好地滿足各種底層資源的訪問(wèn)需求,比如缺少?gòu)念惵窂交蛘遅eb容器上下文中獲取資源的操作類。因此,Spring提供了Resource接口,并由此裝載各種資源,包括配置文件、國(guó)際化屬性文件等資源。
3.1 Resource類圖WritableResource:可寫資源接口,Spring3.1新增的接口,有2個(gè)實(shí)現(xiàn)類:FileSystemResource和PathResource。
ByteArrayResource:二進(jìn)制數(shù)組表示的資源,二進(jìn)制數(shù)組資源可以在內(nèi)存中通過(guò)程序構(gòu)造。
ClassPathResource:類路徑下的資源,資源以相對(duì)于類路徑的方式表示。
FileSystemResouce:文件系統(tǒng)資源,資源以文件系統(tǒng)路徑的方式表示。
InputStreamResource:以輸入流返回標(biāo)識(shí)的資源
ServletContextResource:為訪問(wèn)Web容器上下文中的資源而設(shè)計(jì)的類,負(fù)責(zé)以相對(duì)于Web應(yīng)用根目錄的路徑來(lái)加載資源。支持以流和URL的形式訪問(wèn),在war包解包的情況下,也可以通過(guò)File方式訪問(wèn)。 該類還可以直接從JAR包中訪問(wèn)資源。
UrlResource:封裝了java.net.URL,它使用戶能夠訪問(wèn)任何可以通過(guò)URL表示的資源,如文件系統(tǒng)的資源、HTTP資源、FTP資源
PathResource:Spring 4.0提供的讀取資源文件的新類。PathResource封裝了java.net.URL、java.nio.file.Path、文件系統(tǒng)資源,它使用戶能夠訪問(wèn)任何可以通過(guò)URL、Path、系統(tǒng)文件路徑標(biāo)識(shí)的資源,如文件系統(tǒng)的資源、HTTP資源、FTP資源
3.2 資源加載為了訪問(wèn)不同類型的資源,Resource接口下提供了不同的子類,這造成了使用上的不便。Spring提供了一個(gè)強(qiáng)大的加載資源的方式,在不顯示使用Resource實(shí)現(xiàn)類的情況下,僅通過(guò)不同資源地址的特殊標(biāo)示就可以訪問(wèn)對(duì)應(yīng)的資源。
地址前綴 | 實(shí)例 | 釋義 |
---|---|---|
classpath: | classpath:com/ankeetc/spring/Main.class | 從類不經(jīng)中加載資源,classpath: 和 classpath:/ 是等價(jià)的,都是相對(duì)于類的根路徑,資源文件可以在標(biāo)準(zhǔn)的文件系統(tǒng)中,也可以在jar或者zip的類包中 |
file: | file:/Users/zhengzhaoxi/.gitconfig | 使用UrlResource從文件系統(tǒng)目錄中裝載資源,可以采用絕對(duì)路徑或者相對(duì)路徑 |
http:// | http://spiderlucas.github.io/... | 使用UrlResource從web服務(wù)器中加載資源 |
ftp:// | ftp://spiderlucas.github.io/atom.xml | 使用UrlResource從FTP服務(wù)器中裝載資源 |
沒(méi)有前綴 | com/ankeetc/spring/Main.class | 根據(jù)ApplicationContext的具體實(shí)現(xiàn)類采用對(duì)應(yīng)類型的Resource |
假設(shè)有多個(gè)Jar包或者文件系統(tǒng)類路徑下?lián)碛幸粋€(gè)相同包名(如com.ankeetc):
classpath:只會(huì)在第一個(gè)加載的com.ankeetc包的類路徑下查找
classpath*:會(huì)掃描到所有的這些JAR包及類路徑下出現(xiàn)的com.ankeetc類路徑。
這對(duì)于分模塊打包的應(yīng)用非常有用,假設(shè)一個(gè)應(yīng)用分為2個(gè)模塊,每一個(gè)模塊對(duì)應(yīng)一個(gè)配置文件,分別為module1.yaml 、module2.yaml,都放在了com.ankeetc的目錄下,每個(gè)模塊多帶帶打成JAR包??梢允褂?classpath*:com/ankeetc/module*.xml加載所有模塊的配置文件。
? 匹配文件名中的一個(gè)字符
* 匹配文件名中的任意字符
** 匹配多層路徑
ResourceLoader接口僅有一個(gè)getResource(String loacation)方法,可以根據(jù)一個(gè)資源地址加載文件資源。不過(guò),資源地址僅支持帶資源類型前綴的表達(dá)式,不支持Ant風(fēng)格的資源路徑表達(dá)式。
ResourcePatternResolver擴(kuò)展ResourceLoader接口,定義了一個(gè)新的接口方法getResource(String locationPattern),改方法支持帶資源類型前綴及Ant風(fēng)格的資源路徑表達(dá)式。
PathMatchingResourcePatternResolver是Spring提供的標(biāo)準(zhǔn)實(shí)現(xiàn)類。
4 BeanFactoryBeanFactory是Spring框架最核心的接口,它提供了高級(jí)IoC的配置機(jī)制。我們一般稱BeanFactory為IoC容器。
BeanFactory是Spring框架等基礎(chǔ)設(shè)施,面向Spring本身。
BeanFactory是一個(gè)類工廠,可以創(chuàng)建并管理各種類的對(duì)象。
所有可以被Spring容器實(shí)例化并管理的Java類都可以成為Bean。
BeanFactory主要方法就是getBean(String beanName);
BeanFactory啟動(dòng)IoC容器時(shí),并不會(huì)初始化配置文件中定義的Bean,初始化動(dòng)作在第一個(gè)調(diào)用時(shí)產(chǎn)生。
對(duì)于單實(shí)例的Bean來(lái)說(shuō),BeanFactory會(huì)緩存Bean實(shí)例,在第二次使用geBean()獲取Bean時(shí),將直接從IoC容器的緩存中獲取Bean實(shí)例。
4.1 BeanFactory體系結(jié)構(gòu)BeanFactory:BeanFactory接口位于類結(jié)構(gòu)樹(shù)的頂端,它最主要的方法就是getBean(String beanName) ,該方法從容器中返回特定名稱的Bean,BeanFactory的功能通過(guò)其他接口而得到不斷擴(kuò)展。
ListableBeanFactory:該接口定義了訪問(wèn)容器中Bean基本信息的若干方法,如:查看 Bean 的個(gè)數(shù)、獲取某一類型Bean的配置名、或查看容器中是否包含某一個(gè)Bean。
HierarhicalBeanFactory:父子級(jí)聯(lián) IoC 容器的接口,子容器可以通過(guò)接口方法訪問(wèn)父容器。
ConfigurableBeanFactory:該接口增強(qiáng)了IoC容器的可定制性,它定義了設(shè)置類裝載器、屬性 編輯器、容器初始化后置處理器等方法。
AutowireCapableBeanFactory:定義了將容器中的Bean按某種規(guī)則(如:按名稱匹配、按類型匹配)進(jìn)行自動(dòng)裝配的方法。
SingletonBeanFactory:定義了允許在運(yùn)行期間向容器注冊(cè)單實(shí)例Bean的方法。
BeanDefinitionRegistry:Spring配置文件中每一個(gè)Bean節(jié)點(diǎn)元素在Spring容器里都通過(guò)一個(gè) BeanDefinition對(duì)象表示,它描述了Bean的配置信息。而B(niǎo)eanDefinitionRegistry接口提供了向容器手工注冊(cè)BeanDefinition對(duì)象的方法。
4.2 初始化BeanFactoryBeanFactory有多種實(shí)現(xiàn),最常用的是 XmlBeanFactory,但在Spring 3.2時(shí)已被廢棄。目前建議使用XmlBeanDefinitionReader與DefaultListableBeanFactory。
public static void main(String[] args) throws Exception { ResourceLoader resourceLoader = new DefaultResourceLoader(); Resource resource = resourceLoader.getResource("beans.xml"); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); reader.loadBeanDefinitions(resource); beanFactory.getBean(""); }4.3 BeanFactory中Bean的生命周期
當(dāng)調(diào)用者通過(guò)getBean()向容器請(qǐng)求一個(gè)Bean時(shí),如果容器注冊(cè)了InstantiationAwareBeanPostProcessor接口,則在實(shí)例化Bean之前,調(diào)用postProcessBeforeInstantiation()方法。
根據(jù)配置調(diào)用構(gòu)造方法或者工廠方法實(shí)例化Bean。
調(diào)用InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()。
調(diào)用InstantiationAwareBeanPostProcessor#postProcessPropertyValues()方法。
設(shè)置屬性值。
如果Bean實(shí)現(xiàn)了BeanNameAware接口,則將調(diào)用BeanNameAware#setBeanName()接口方法,將配置文件中該Bean對(duì)應(yīng)的名稱設(shè)置到Bean中。
如果Bean實(shí)現(xiàn)了BeanFactoryAware接口,將調(diào)用BeanFactoryAware#setBeanFactory()接口方法。
如果容器注冊(cè)了BeanPostProcessor接口,將調(diào)用BeanPostProcessor#postProcessBeforeInitialization()方法。入?yún)ean是當(dāng)前正在處理的Bean,BeanName是當(dāng)前Bean的配置名,返回的對(duì)象為處理后的Bean。BeanPostProcessor在Spring框架中占有重要的地位,為容器提供對(duì)Bean進(jìn)行后續(xù)加工處理的切入點(diǎn),AOP、動(dòng)態(tài)代理都通過(guò)BeanPostProcessor來(lái)實(shí)現(xiàn)。
如果Bean實(shí)現(xiàn)了InitializingBean接口,則將調(diào)用InitializingBean#afterPropertiesSet()方法。
如果
調(diào)用BeanPostProcessor#postProcessAfterInitialization()方法再次加工Bean。
如果
對(duì)于scope="singleton"的Bean,當(dāng)容器關(guān)閉時(shí),將觸發(fā)Spring對(duì)Bean的后續(xù)生命周期的管理工作。如果Bean實(shí)現(xiàn)了DisposableBean接口,將調(diào)用DisposableBean#destroy()方法。
對(duì)于`scope="singleton"的Bean,如果通過(guò)
Bean自身的方法:構(gòu)造方法、Setter設(shè)置屬性值、init-method、destroy-method。
Bean級(jí)生命周期接口方法:如上圖中藍(lán)色的部分。BeanNameAware、BeanFactoryAware、InitializingBean、DisposableBean,這些由Bean本身直接實(shí)現(xiàn)。
容器級(jí)生命周期接口方法:如上圖中的紅色的部分。InstantiationAwareBeanPostProcessor和BeanPostProcessor這兩個(gè)接口,一般稱它們的實(shí)現(xiàn)類為后處理器。后處理器接口不由Bean本身實(shí)現(xiàn),實(shí)現(xiàn)類以容器附加裝置的形式注冊(cè)到Spring容器中。當(dāng)Spring容器創(chuàng)建任何Bean的時(shí)候,這些后處理器都會(huì)起作用,所以這些后處理器的影響是全局的。如果需要多個(gè)后處理器,可以同時(shí)實(shí)現(xiàn)Ordered接口,容器將按照特定的順序依此調(diào)用這些后處理器。
工廠后處理器接口方法:AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等方法,工廠后處理器也是容器級(jí)的,在應(yīng)用上下文裝配配置文件后立即使用。
4.4 BeanFactory生命周期案例public class Main { public static void main(String[] args) { Resource resource = new PathMatchingResourcePatternResolver().getResource("classpath:beans.xml"); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); reader.loadBeanDefinitions(resource); beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() { public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException { System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()"); return null; } public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()"); return true; } public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { System.out.println("InstantiationAwareBeanPostProcessor.postProcessPropertyValues()"); return pvs; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("BeanPostProcessor.postProcessBeforeInitialization()"); return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("BeanPostProcessor.postProcessAfterInitialization()"); return bean; } }); MyBean myBean = beanFactory.getBean("myBean", MyBean.class); beanFactory.destroySingletons(); } } class MyBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean { private String prop; public MyBean() { System.out.println("MyBean:構(gòu)造方法"); } public String getProp() { System.out.println("MyBean:get方法"); return prop; } public void setProp(String prop) { System.out.println("MyBean:set方法"); this.prop = prop; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("MyBean:BeanFactoryAware.setBeanFactory()"); } public void setBeanName(String name) { System.out.println("MyBean:BeanNameAware.setBeanName()"); } public void destroy() throws Exception { System.out.println("MyBean:DisposableBean.destroy()"); } public void afterPropertiesSet() throws Exception { System.out.println("MyBean:InitializingBean.afterPropertiesSet()"); } // 配置文件中init-method public void myInit() { System.out.println("MyBean:myInit()"); } // 配置文件中destroy-method public void myDestroy() { System.out.println("MyBean:myDestroy()"); } }
4.5 關(guān)于Bean生命周期接口的探討
Bean生命周期帶來(lái)的耦合:通過(guò)實(shí)現(xiàn)Spring的Bean生命周期接口對(duì)Bean進(jìn)行額外控制,雖然讓Bean具有了更細(xì)致的生命周期階段,但也帶來(lái)了一個(gè)問(wèn)題,Bean和Spring框架緊密綁定在一起了,這和Spring一直推崇的“不對(duì)應(yīng)用程序類作任何限制”的理念是相悖的。業(yè)務(wù)類本應(yīng)該完全POJO化,只實(shí)現(xiàn)自己的業(yè)務(wù)接口,不需要和某個(gè)特定框架(包括Spring框架)的接口關(guān)聯(lián)。
init-method和destroy-method:可以通過(guò)
BeanPostProcessor:BeanPostProcessor接口不需要Bean去繼承它,可以像插件一樣注冊(cè)到Spring容器中,為容器提供額外功能。
5 ApplicationContext 5.1 Application體系結(jié)構(gòu)ApplicationEventPublisher:讓容器擁有了發(fā)布應(yīng)用上下文事件的功能,包括容器啟動(dòng)事件 、關(guān)閉事件等。實(shí)現(xiàn)了ApplicationListener事件監(jiān)聽(tīng)接口的Bean可以接收到容器事件,并對(duì)容器事件進(jìn)行響應(yīng)處理。在ApplicationContext抽象實(shí)現(xiàn)類AbstractApplicationContext中存在一個(gè) ApplicationEventMulticaster,它負(fù)責(zé)保存所有的監(jiān)聽(tīng)器,以便在容器產(chǎn)生上下文事件時(shí)通知這些事件監(jiān)聽(tīng)者。
MessageSource:為容器提供了i18n國(guó)際化信息訪問(wèn)的功能。
ResourcePatternResolver:所有ApplicationContext實(shí)現(xiàn)類都實(shí)現(xiàn)了類似于PathMatchingResourcePatternResolver的功能,可以通過(guò)帶前綴 Ant 風(fēng)格的資源類文件路徑來(lái)裝載Spring的配置文件。
LifeCycle:它提供了start()和stop()兩個(gè)方法,主要用于控制異步處理過(guò)程。在具體使用時(shí),該接口同時(shí)被ApplicationContext實(shí)現(xiàn)及具體Bean實(shí)現(xiàn),ApplicationContext會(huì)將start/stop的信息傳遞給容器中所有實(shí)現(xiàn)了該接口的Bean,以達(dá)到管理和控制JMX、任務(wù)調(diào)度等目的。
ConfigurableApplicationContext:它擴(kuò)展了ApplicationContext,讓ApplicationContext具有啟動(dòng)、刷新和關(guān)閉應(yīng)用上下文的能力。上下文關(guān)閉時(shí),調(diào)用 refresh()即可啟動(dòng)上下文;如果已經(jīng)啟動(dòng),則調(diào)用refresh()可清除緩存并重新加載配置信息;調(diào)用close()可關(guān)閉應(yīng)用上下文。
5.2 初始化ApplicationContextClassPathXmlApplicationContext:從類路徑中加載XML配置文件,也可以顯示的使用帶資源類型前綴的路徑。
FileSystemXmlApplicationContext:從文件系統(tǒng)路徑下加載XML配置文件,也可以顯示的使用帶資源類型前綴的路徑。
AnnotationConfigApplicationContext:一個(gè)標(biāo)注@Configuration注解的POJO即可提供Spring所需的Bean配置信息。
GenericGroovyApplicationContext:從Groovy配置中提取Bean。
public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml"); FileSystemXmlApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext("file:/Users/zhengzhaoxi/Git/spring/src/main/resources/beans.xml"); AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class); }5.3 WebApplicationContext體系結(jié)構(gòu)
見(jiàn)后續(xù)章節(jié)
5.4 ApplicationContext中Bean的生命周期Bean在ApplicationContext和BeanFactory中生命周期類似,但有以下不同點(diǎn)
如果Bean實(shí)現(xiàn)了ApplicationContextAware接口,則會(huì)增加一個(gè)調(diào)用該接口方法的ApplicationContextAware.setApplicationContext的方法。
如果在配置文件中生命了工廠后處理器接口BeanFactoryPostProcessor的實(shí)現(xiàn)類,則應(yīng)用上下文在裝在配置文件之后、初始化Bean實(shí)例之前會(huì)調(diào)用這些BeanFactoryPostProcessor對(duì)配置信息進(jìn)行加工處理。Spring提供了多個(gè)工廠容器,如CustomEditorConfigure、PropertyPlaceholderConfigurer等。工廠后處理器是容器級(jí)的,只在應(yīng)用上下文初始化時(shí)調(diào)用一次,其目的是完成一些配置文件加工處理工作。
ApplicationContext可以利用Java反射機(jī)制自動(dòng)識(shí)別出配置文件中定義的BeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanFactoryPostProcessor,并自動(dòng)將它們注冊(cè)到應(yīng)用上下文中(如下所示);而B(niǎo)eanFactory需要通過(guò)手工調(diào)用addBeanPostProcessor()方法注冊(cè)。
6 BeanFactory與ApplicationContext區(qū)別
一般稱BeanFactory為IoC容器:Bean工廠(com.springframework.beans.factory.BeanFactory)是Spring框架中最核心的接口,它提供了高級(jí) IoC 的配置機(jī)制 。BeanFactory使管理不同類型的Java對(duì)象成為可能。BeanFactory是Spring框架的基礎(chǔ)設(shè)施,面向Spring本身。
一般稱ApplicationContext為應(yīng)用上下文或Spring容器:應(yīng)用上下文(com.springframework.context.ApplicationContext)建立在BeanFactory基礎(chǔ)之上,提供了更多面向應(yīng)用的功能,它提供了國(guó)際化支持和框架事件體系,更易于創(chuàng)建實(shí)際應(yīng)用 。 ApplicationContext 面向使用 Spring 框架的開(kāi)發(fā)者,幾乎所有的應(yīng)用場(chǎng)合都可以直接使用 ApplicationContext。
BeanFactory在初始化容器的時(shí)候,并未實(shí)例化Bean,直到第一次訪問(wèn)某個(gè)Bean時(shí)才實(shí)例化Bean;ApplicationContext在初始化應(yīng)用上下文的時(shí)候就實(shí)例化全部單實(shí)例Bean。
ApplicationContext可以利用Java反射機(jī)制自動(dòng)識(shí)別出配置文件中定義的BeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanFactoryPostProcessor,并自動(dòng)將它們注冊(cè)到應(yīng)用上下文中;而B(niǎo)eanFactory需要通過(guò)手工調(diào)用addBeanPostProcessor()方法注冊(cè)。
7 父子容器通過(guò)HierarchicalBeanFactory接口,Spring的IoC容器可以建立父子層級(jí)關(guān)聯(lián)的容器體系,子容器可以訪問(wèn)父容器中的 Bean,但父容器不能訪問(wèn)子容器的Bean。
在容器內(nèi),Bean的id必須是唯一的,但子容器可以擁有一個(gè)和父容器id相同的 Bean。
父子容器層級(jí)體系增強(qiáng)了Spring容器架構(gòu)的擴(kuò)展性和靈活性,因此第三方可以通過(guò)編程的方式,為一個(gè)已經(jīng)存在的容器添加一個(gè)或多個(gè)特殊用途的子容器,以提供一些額外的功能。
Spring使用父子容器的特性實(shí)現(xiàn)了很多能力,比如在Spring MVC中,展現(xiàn)層Bean位于一個(gè)子容器中,而業(yè)務(wù)層和持久層的Bean位于父容器中。 這樣展現(xiàn)層Bean就可以引用業(yè)務(wù)層和持久層的Bean,而業(yè)務(wù)層和持久層的Bean則看不到展現(xiàn)層的Bean。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/72862.html
摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開(kāi)發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過(guò)的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛(ài)情萌芽的模樣…… Java 進(jìn)階面試問(wèn)題列表 -...
摘要:開(kāi)啟自動(dòng)配置功能后文詳解這個(gè)注解,學(xué)過(guò)的同學(xué)應(yīng)該對(duì)它不會(huì)陌生,就是掃描注解,默認(rèn)是掃描當(dāng)前類下的。簡(jiǎn)單來(lái)說(shuō),這個(gè)注解可以幫助我們自動(dòng)載入應(yīng)用程序所需要的所有默認(rèn)配置。簡(jiǎn)單理解這二者掃描的對(duì)象是不一樣的。 前言 只有光頭才能變強(qiáng)。 文本已收錄至我的GitHub倉(cāng)庫(kù),歡迎Star:https://github.com/ZhongFuCheng3y/3y 回顧前面Spring的文章(以學(xué)習(xí)...
摘要:學(xué)習(xí)總結(jié)學(xué)習(xí)整理的一些筆記,很簡(jiǎn)單。大部分認(rèn)為和只是不同的叫法而已。依賴注入的兩種方式和注解使用注釋驅(qū)動(dòng)的功能源碼剖析 Spring IoC學(xué)習(xí)總結(jié) 學(xué)習(xí)spring Ioc整理的一些筆記,很簡(jiǎn)單。分享給大家。 IoC 基本概念 在這之前,我們先記住一句話。好萊塢原則:Dont call us, we will call you.其實(shí)這句話很恰當(dāng)?shù)匦稳萘朔崔D(zhuǎn)的意味;Ioc, Inve...
摘要:構(gòu)造函數(shù)注入通過(guò)調(diào)用類的構(gòu)造函數(shù),將接口實(shí)現(xiàn)類通過(guò)構(gòu)造函數(shù)變量傳入。而在中,其使用橫切技術(shù),將這類代碼從原屬的封裝對(duì)象中提取出來(lái),封裝到一個(gè)可重用模塊中,稱為。 最近實(shí)習(xí)用到Spring的開(kāi)發(fā)框架,但是之前沒(méi)有接觸過(guò),因此希望利用網(wǎng)上的資源來(lái)學(xué)習(xí)以下。 Spring官方給出了非常全面的介紹,非常適合我這種完全的小白……在這一系列學(xué)習(xí)中,我閱讀的主要資源是5.1.2 Reference ...
閱讀 1686·2021-11-23 09:51
閱讀 1231·2019-08-30 13:57
閱讀 2325·2019-08-29 13:12
閱讀 2065·2019-08-26 13:57
閱讀 1257·2019-08-26 11:32
閱讀 1039·2019-08-23 15:08
閱讀 789·2019-08-23 14:42
閱讀 3137·2019-08-23 11:41