日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

框架:spring总结

發(fā)布時間:2025/3/21 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 框架:spring总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

struts 是 web 框架 (jsp/action/actionfrom)?

hibernate 是 orm框架,處于持久層.

那么,什么是Spring?

spring 是容器框架,用于配置bean,并維護bean之間關系的框架 。

spring中非常重要的概念:bean,ioc,di


一個簡單的spring入門項目.


spring實際上是一個容器框架,可以配置各種bean(action/service/domain/dao),并且可以維護bean與bean的關系,當我們需要使用某個bean的時候,我們可以getBean(id),使用即可.

什么是bean?

Bean在Spring和SpringMVC中無所不在,將這個概念內(nèi)化很重要,下面分享一下我的想法:

一、Bean是啥

1、Java面向?qū)ο?#xff0c;對象有方法和屬性,那么就需要對象實例來調(diào)用方法和屬性(即實例化)

2、凡是有方法或?qū)傩缘念惗夹枰獙嵗?/span>,這樣才能具象化去使用這些方法和屬性;

3、規(guī)律:凡是子類及帶有方法或?qū)傩缘念惗家由?注冊Bean到Spring IoC的注解

(@Component , @Repository , @ Controller , @Service , @Configration)

4、把Bean理解為類的代理或代言人(實際上確實是通過反射、代理來實現(xiàn)的),這樣它就能代表類擁有該擁有的東西了

5、我們都在微博上@過某某,對方會優(yōu)先看到這條信息,并給你反饋,那么在Spring中,你標識一個@符號,那么Spring就會來看看,并且從這里拿到一個Bean(注冊)或者給出一個Bean(使用)

二、注解分為兩類:

1、一類是使用Bean,即是把已經(jīng)在xml文件中配置好的Bean拿來用,完成屬性、方法的組裝;

比如@Autowired , @Resource,可以通過byTYPE(@Autowired)、byNAME(@Resource)的方式獲取Bean;

?

2、一類是注冊Bean,@Component , @Repository , @ Controller , @Service , @Configration這些注解都是把你要實例化的對象轉(zhuǎn)化成一個Bean,放在IoC容器中,等你要用的時候,它會和上面的@Autowired , @Resource配合到一起,把對象、屬性、方法完美組裝。

?

三、@Bean是啥?

?

1、原理是什么?先看下源碼中的部分內(nèi)容:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Indicates that a method produces a bean to be managed?by?the Spring container.

?

?<h3>Overview</h3>

?

?<p>The names and semantics of the attributes to?this?annotation are intentionally

?similar to those of the {@code <bean/>} element?in?the Spring XML schema. For

?example:

?

?<pre?class="code">

?????@Bean

?????public?MyBean myBean() {

?????????// instantiate and configure MyBean obj

?????????return?obj;

????}</pre>

  意思是@Bean明確地指示了一種方法,什么方法呢——產(chǎn)生一個bean的方法,并且交給Spring容器管理從這我們就明白了為啥@Bean是放在方法的注釋上了,因為它很明確地告訴被注釋的方法,你給我產(chǎn)生一個Bean,然后交給Spring容器,剩下的你就別管了。

?2、記住,@Bean就放在方法上,就是產(chǎn)生一個Bean,那你是不是又糊涂了,因為已經(jīng)在你定義的類上加了@Configration等注冊Bean的注解了,為啥還要用@Bean呢?這個我也不知道,下面我給個例子,一起探討一下吧:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

3

package?com.edu.fruit;

??//定義一個接口

????public?interface?Fruit<T>{

????????//沒有方法

}

?

/*

*定義兩個子類

*/

package?com.edu.fruit;

?????@Configuration

?????public?class?Apple?implements?Fruit<Integer>{//將Apple類約束為Integer類型

?

}

?

package?com.edu.fruit;

?????@Configuration

?????public?class?GinSeng?implements?Fruit<String>{//將GinSeng 類約束為String類型

?

}

/*

*業(yè)務邏輯類

*/

package?com.edu.service;

???????@Configuration

???????public?class?FruitService {

??????????@Autowired

??????????private?Apple apple;

??????????@Autowired

??????????private?GinSeng ginseng;

????//定義一個產(chǎn)生Bean的方法

???????@Bean(name="getApple")

???????public?Fruit<?> getApple(){

???????System.out.println(apple.getClass().getName().hashCode());

?????????System.out.println(ginseng.getClass().getName().hashCode());

???????return?new?Apple();

}

}

/*

*測試類

*/

@RunWith(BlockJUnit4ClassRunner.class)

public?class?Config {

????public?Config(){

????????super("classpath:spring-fruit.xml");

????}

????@Test

????public?void?test(){

????????super.getBean("getApple");//這個Bean從哪來,從上面的@Bean下面的方法中來,返回

??????????????????????????????????????????????????????????的是一個Apple類實例對象

?????????

????}

}

從上面的例子也印證了我上面的總結的內(nèi)容:

1、凡是子類及帶屬性、方法的類都注冊Bean到Spring中,交給它管理;

2、@Bean 用在方法上,告訴Spring容器,你可以從下面這個方法中拿到一個Bean


什么是IOC?

IOC,控制反轉(zhuǎn);所謂控制反轉(zhuǎn)就是把創(chuàng)建對象和維護對象關系的權利轉(zhuǎn)移到Spring容器(applicationContext.xml)中,而程序本身不在維護!

什么是DI?

依賴注入,容易維護好對象之間的依賴關系(引用等),就是當程序需要對象的時候,容器將對象注入到程序中,程序此時也依賴容器的對象注入。實際上di和ioc是同一個概念,spring設計者認為di更準確表示spring核心技術。


1.bean容器中獲取bean對象的方法

1)從ApplicationContext應用上下文容器中獲取

ApplicationContext applicationContext = new ClassPathXmlApplicationContext(".xml文件");

? 三種獲取上下文的方法:

??? 1.ClassPathXmlApplicationContext?從類路徑加載

??? 2.FileSystemXmlApplicationContext? 從文件系統(tǒng)中加載

??? 3.XmlWebApplicationContext?? 從web系統(tǒng)中加載?

2)從bean工廠中獲取(BeanFactory)?

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(".xml文件"));

兩種方式的比較:

1)加載XML時,ApplicationContext實例化容器的時候,實例化所有對象。當我們要使用的時候,直接獲取。即方便快捷,提前加載,但是浪費內(nèi)存。(餓漢

2)加載XML時,BeanFactory實例化容器但不會實例化所配置的bean對象,只有當我們getBean的時候,才會創(chuàng)建。懶漢

在沒有特殊要求的時候,一般使用ApplicationContext

Spring底層對象實例的創(chuàng)建是基于反射和HashMap機制

?


2.bean的scope

默認的生命周期是singleton 單例模式


3.配置bean ?如何給集合類型注入值.?

java中主要的集合有幾種: map set list / 數(shù)組

Department類:

package com.hsp.collection;import java.util.List; import java.util.Map; import java.util.Set;public class Department {private String name;private String[] empName;private List<Employee> empList;private Set<Employee> empsets;private Map<String,Employee> empMaps;private properties pp;public Set<Employee> getEmpsets() {return empsets;}public void setEmpsets(Set<Employee> empsets) {this.empsets = empsets;}public String[] getEmpName() {return empName;}public void setEmpName(String[] empName) {this.empName = empName;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<Employee> getEmpList() {return empList;}public void setEmpList(List<Employee> empList) {this.empList = empList;}public Map<String, Employee> getEmpMaps() {return empMaps;}public void setEmpMaps(Map<String, Employee> empMaps) {this.empMaps = empMaps;}}

Employeel類

package com.hsp.collection; public class Employee {private String name;private int id;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;} }

beans.xml配置文件:

<?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"><bean id="department" class="com.hsp.collection.Department"> <property name="name" value="財務部"/><!-- 給數(shù)組注入值 --> <property name="empName"><list><value>小明</value><value>小明小明</value><value>小明小明小明小明</value></list> </property><!-- 給list注入值 list 中可以有相當?shù)膶ο?--> <property name="empList"><list><ref bean="emp2" /><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/><ref bean="emp1"/></list> </property><!-- 給set注入值 set不能有相同的對象 --> <property name="empsets"><set><ref bean="emp1" /><ref bean="emp2"/><ref bean="emp2"/><ref bean="emp2"/><ref bean="emp2"/></set> </property><!-- 給map注入值 map只有key不一樣,就可以裝配value --> <property name="empMaps"><map><entry key="11" value-ref="emp1" /> <entry key="22" value-ref="emp2"/><entry key="33" value-ref="emp1"/></map> </property><!-- 給屬性集合配置 【點http協(xié)議 referer 】--> <property name="pp"><props><prop key="pp1">abcd</prop><prop key="pp2">hello</prop></props> </property> </bean><bean id="emp1" class="com.hsp.collection.Employee"> <property name="name" value="北京"/> <property name="id" value="1"/> </bean><bean id="emp2" class="com.hsp.collection.Employee"> <property name="name" value="天津"/> <property name="id" value="2"/> </bean></beans>

4.內(nèi)部bean,也就是bean的嵌套

<bean id=”foo” class=”....Foo”><property name=”屬性”><!—第一方法引用--><ref bean=’bean對象名’/><!—內(nèi)部bean--><bean> <properyt></property> </bean> </property> </bean>

5.繼承配置

public class Student

public class Gradate extends Student

在beans.xml文件中體現(xiàn)配置

<!-- 配置一個學生對象 --> <bean id="student" class="com.hsp.inherit.Student"><property name="name" value="順平" /><property name="age" value="30"/> </bean><!-- 配置Grdate對象 --> <bean id="grdate" parent="student" class="com.hsp.inherit.Gradate"><!-- 如果自己配置屬性name,age,則會替換從父對象繼承的數(shù)據(jù) --><property name="name" value="小明"/><property name="degree" value="學士"/> </bean>

6.通過properties取數(shù)據(jù)(接上面的例子)

properties pp = department.getPp(); for(Entry<Object,Object>entry:pp.entrySet()){System.out.println(entry.getKey().toString()+" "+entry.getValue());}

7.按照構造函數(shù)方法注入bean?? (類中必須要有構造函數(shù))

beans.xml 關鍵代碼:

<!-- 配置一個雇員對象 --> <bean id="employee" class="com.hsp.constructor.Employee"> <!-- 通過構造函數(shù)來注入屬性值 --> <constructor-arg index="0" type="java.lang.String" value="大明" /> </bean>

8.自動裝配

1.byName

<!-- 配置一個master對象 --> <bean id="master" class="com.hsp.autowire.Master" autowire="byName"> <property name="name"> <value>順平</value> </property> </bean> <!-- 配置dog對象 --> <bean id="dog" class="com.hsp.autowire.Dog"> <property name="name" value="小黃"/> <property name="age" value="3"/> </bean>

2.byType: byType:尋找和屬性類型相同的bean,找不到,裝不上,找到多個拋異常。

3.constructor: autowire="constructor"?? 查找和bean的構造參數(shù)一致的一個或多個bean,若找不到或找到多個,拋異常。

按照參數(shù)的類型裝配? 。

4.?autodetect?? (3)和(2)之間選一個方式。不確定性的處理與(3)和(2)一致。 (construct優(yōu)先級要高)

5.default

這個需要在<beans defualt-autorwire=“指定”?/>

當你在<beans >指定了 default-atuowrite后, 所有的bean的 默認的autowire就是 指定的裝配方法;

如果沒有在<beans defualt-autorwire=“指定”?/> 沒有 ?defualt-autorwire=“指定”?,則默認是

defualt-autorwire=”no”

6.no? 不自動裝配


9.使用spring的特殊bean,完成分散配置

??? 創(chuàng)建properties文件,將所有的屬性值按照key-value的形式放入文件中。

<context:property-placeholder location=".properties文件路徑"/> <!-- 配置一DBUtil對象 $占位符號 --> <bean id="dbutil" class="com.hsp.dispatch.DBUtil"> <property name="name" value="${name}" /> <property name="drivername" value="${drivername}" /> <property name="url" value="${url}" /> <property name="pwd" value="${pwd}" /> </bean><!-- 配置一DBUtil對象 --> <bean id="dbutil2" class="com.hsp.dispatch.DBUtil"> <property name="name" value="${db2.name}" /> <property name="drivername" value="${db2.drivername}" /> <property name="url" value="${db2.url}" /> <property name="pwd" value="${db2.pwd}" /> </bean>

db.properties:

name=scott drivername=oracle:jdbc:driver:OracleDirver url=jdbc:oracle:thin:@127.0.0.1:1521:hsp pwd=tiger

啟用類中的注解

<context:annotation-config/>


Bean的作用域

?Spring3中為Bean定義了5中作用域,

分別為singleton(單例)、prototype(原型)、request、session和global session,5種作用域說明如下:

1.??? singleton:單例模式,Spring IoC容器中只會存在一個共享的Bean實例,無論有多少個Bean引用它,始終指向同一對象。Singleton作用域是Spring中的缺省作用域,也可以顯示的將Bean定義為singleton模式,配置為:

·????????<bean id="userDao"class="com.ioc.UserDaoImpl" scope="singleton"/>

2.??? prototype:原型模式,每次通過Spring容器獲取prototype定義的bean時,容器都將創(chuàng)建一個新的Bean實例,每個Bean實例都有自己的屬性和狀態(tài),而singleton全局只有一個對象。

根據(jù)經(jīng)驗,對有狀態(tài)的bean使用prototype作用域,而對無狀態(tài)的bean使用singleton作用域。

3.??? request:在一次Http請求中,容器會返回該Bean的同一實例。而對不同的Http請求則會產(chǎn)生新的Bean,而且該bean僅在當前Http Request內(nèi)有效。

·????????<bean id="loginAction" class="com.cnblogs.Login "scope="request"/>,針對每一次Http請求,Spring容器根據(jù)該bean的定義創(chuàng)建一個全新的實例,且該實例僅在當前Http請求內(nèi)有效,而其它請求無法看到當前請求中狀態(tài)的變化,當當前Http請求結束,該bean實例也將會被銷毀。

4.??? session:在一次Http Session中,容器會返回該Bean的同一實例。而對不同的Session請求則會創(chuàng)建新的實例,該bean實例僅在當前Session內(nèi)有效。

·????????<beanid="userPreference" class="com.ioc.UserPreference"scope="session"/>,同Http請求相同,每一次session請求創(chuàng)建新的實例,而不同的實例之間不共享屬性,且實例僅在自己的session請求內(nèi)有效,請求結束,則實例將被銷毀。

5.??? global Session:在一個全局的Http Session中,容器會返回該Bean的同一個實例,僅在使用portlet context時有效。


?Bean的生命周期

經(jīng)過如上對Bean作用域的介紹,接下來將在Bean作用域的基礎上講解Bean的生命周期

  Spring容器可以管理singleton作用域下Bean的生命周期,在此作用域下,Spring能夠精確地知道Bean何時被創(chuàng)建,何時初始化完成,以及何時被銷毀。而對于prototype作用域的Bean,Spring只負責創(chuàng)建,當容器創(chuàng)建了Bean的實例后,Bean的實例就交給了客戶端的代碼管理,Spring容器將不再跟蹤其生命周期,并且不會管理那些被配置成prototype作用域的Bean的生命周期。Spring中Bean的生命周期的執(zhí)行是一個很復雜的過程,讀者可以利用Spring提供的方法來定制Bean的創(chuàng)建過程Spring容器在保證一個bean實例能夠使用之前會做很多工作:

1.Spring對Bean進行實例化(相當于程序中的new Xx())

2.Spring將值和Bean的引用注入進Bean對應的屬性中,也就是IOC注入

3.如果Bean實現(xiàn)了BeanNameAware接口,Spring將Bean的ID傳遞給setBeanName()方法
(實現(xiàn)BeanNameAware主要是為了通過Bean的引用來獲得Bean的ID,一般業(yè)務中是很少有用到Bean的ID的

4.如果Bean實現(xiàn)了BeanFactoryAware接口,Spring將調(diào)用setBeanDactory(BeanFactory)方法并把BeanFactory容器實例作為參數(shù)傳入。
(實現(xiàn)BeanFactoryAware 主要目的是為了獲取Spring容器(為了獲得容器,從而調(diào)用容器里的東西),如Bean通過Spring容器發(fā)布事件等)
傳遞的是Spring工廠本身(可以用這個方法獲取到其他Bean)

5.(可以用這個方法獲取到其他Bean,項目中用到了,傳回class)如果Bean實現(xiàn)了ApplicationContextAwaer接口,Spring容器將調(diào)用setApplicationContext(ApplicationContext)方法, (作用與BeanFactory類似都是為了獲取Spring容器,如Bean通過Spring容器發(fā)布事件等,項目是調(diào)用容器里為Handler的bean。applicationContext.getBeansOfType(EventHandler.class);

取得所有的事件處理的classbean做進一步的消費者事件處理2),不同的是Spring容器在調(diào)用setApplicationContext方法時會把它自己作為setApplicationContext 的參數(shù)傳入,而Spring容器在調(diào)用setBeanDactory前需要程序員自己指定(注入)setBeanDactory里的參數(shù)BeanFactory )傳入Spring上下文,該方式同樣可以實現(xiàn)步驟4,但比4更好,因為ApplicationContext是BeanFactory的子接口,有更多的實現(xiàn)方法.(如果應用Spring的工廠也就是BeanFactory的話去掉這一步就Ok了

?)

?

6.如果Bean實現(xiàn)了BeanPostProcess接口,Spring將調(diào)用它們的postProcessBeforeInitialization(預初始化)方法
(作用是在Bean實例創(chuàng)建成功后對進行增強處理,如對Bean進行修改,增加某個功能)

7.如果Bean實現(xiàn)了InitializingBean接口,Spring將調(diào)用它們的afterPropertiesSet方法,作用與在配置文件中對Bean使用init-method聲明初始化的作用一樣,都是在Bean的全部屬性設置成功后執(zhí)行的初始化方法

8.如果Bean實現(xiàn)了BeanPostProcess接口,Spring將調(diào)用它們的postProcessAfterInitialization(后初始化)方法
(作用與6的一樣,只不過6是在Bean初始化前執(zhí)行的,而這個是在Bean初始化后執(zhí)行的,時機不同 )

9.經(jīng)過以上的工作后,Bean準備就緒,將一直駐留在應用上下文中給應用使用,直到應用上下文被銷毀.

?

當Bean不再需要時,會經(jīng)過清理階段。

10.如果Bean實現(xiàn)了DispostbleBean接口,Spring將調(diào)用它的destory方法,

11.如果在配置文件中對Bean使用destory-method屬性,作用跟10是都一樣,都是在Bean實例銷毀前執(zhí)行的方法。

1. 實例化Bean

對于BeanFactory容器,當客戶向容器請求一個尚未初始化的bean時,或初始化bean的時候需要注入另一個尚未初始化的依賴時,容器就會調(diào)用createBean進行實例化。
對于ApplicationContext容器,當容器啟動結束后,便實例化所有的bean。
容器通過獲取BeanDefinition對象中的信息進行實例化。并且這一步僅僅是簡單的實例化,并未進行依賴注入。
實例化對象被包裝在BeanWrapper對象中,BeanWrapper提供了設置對象屬性的接口,從而避免了使用反射機制設置屬性。

2. 設置對象屬性(依賴注入)

實例化后的對象被封裝在BeanWrapper對象中,并且此時對象仍然是一個原生的狀態(tài),并沒有進行依賴注入。
緊接著,Spring根據(jù)BeanDefinition中的信息進行依賴注入。
并且通過BeanWrapper提供的設置屬性的接口完成依賴注入。

3. 注入Aware接口

緊接著,Spring會檢測該對象是否實現(xiàn)了xxxAware接口,并將相關的xxxAware實例注入給bean。(自動裝配過程)

4. BeanPostProcessor

當經(jīng)過上述幾個步驟后,bean對象已經(jīng)被正確構造,但如果你想要對象被使用前再進行一些自定義的處理,就可以通過BeanPostProcessor接口實現(xiàn)
該接口提供了兩個函數(shù):

  • postProcessBeforeInitialzation( Object bean, String beanName )
    當前正在初始化的bean對象會被傳遞進來,我們就可以對這個bean作任何處理。
    這個函數(shù)會先于InitialzationBean執(zhí)行,因此稱為前置處理。
    所有Aware接口的注入就是在這一步完成的。
  • postProcessAfterInitialzation( Object bean, String beanName )
    當前正在初始化的bean對象會被傳遞進來,我們就可以對這個bean作任何處理。
    這個函數(shù)會在InitialzationBean完成后執(zhí)行,因此稱為后置處理。

5. InitializingBean與init-method

當BeanPostProcessor的前置處理完成后就會進入本階段。
InitializingBean接口只有一個函數(shù):

  • afterPropertiesSet()//項目中用到這個。則在注冊bean時,同時執(zhí)行

這一階段也可以在bean正式構造完成前增加我們自定義的邏輯,但它與前置處理不同,由于該函數(shù)并不會把當前bean對象傳進來,因此在這一步?jīng)]辦法處理對象本身,只能增加一些額外的邏輯。
若要使用它,我們需要讓bean實現(xiàn)該接口,并把要增加的邏輯寫在該函數(shù)中。然后Spring會在前置處理完成后檢測當前bean是否實現(xiàn)了該接口,并執(zhí)行afterPropertiesSet函數(shù)。

當然,Spring為了降低對客戶代碼的侵入性,給bean的配置提供了init-method屬性,該屬性指定了在這一階段需要執(zhí)行的函數(shù)名。Spring便會在初始化階段執(zhí)行我們設置的函數(shù)。init-method本質(zhì)上仍然使用了InitializingBean接口(執(zhí)行的初始化方法)。

6. DisposableBean和destroy-method

和init-method一樣,通過給destroy-method指定函數(shù),就可以在bean銷毀前執(zhí)行指定的邏輯。


Spring的單例實現(xiàn)

下面我們來看看Spring中的單例實現(xiàn),當我們試圖從Spring容器中取得某個類的實例時,默認情況下,Spring會才用單例模式進行創(chuàng)建。

<bean id="date" class="java.util.Date"/>

<bean id="date" class="java.util.Date"?scope="singleton"/> (僅為Spring2.0支持)

<bean id="date" class="java.util.Date"?singleton="true"/>

以上三種創(chuàng)建對象的方式是完全相同的,容器都會向客戶返回Date類的單例引用。那么如果我不想使用默認的單例模式,每次請求我都希望獲得一個新的對象怎么辦呢?很簡單,將scope屬性值設置為prototype(原型)就可以了

<bean id="date" class="java.util.Date"?scope="prototype"/>

通過以上配置信息,Spring就會每次給客戶端返回一個新的對象實例。


那么Spring對單例的底層實現(xiàn),到底是餓漢式單例還是懶漢式單例呢?

Spring框架對單例的支持是采用單例注冊表的方式進行實現(xiàn)的,源碼如下:

1.? public?abstract?class?AbstractBeanFactory?implements?ConfigurableBeanFactory{????

2.? ???/**??

3.? ????*?充當了Bean實例的緩存,實現(xiàn)方式和單例注冊表相同??

4.? ????*/????

5.? ???private?final?Map?singletonCache=new?HashMap();????

6.? ???public?Object?getBean(String?name)throws?BeansException{????

7.? ???????return?getBean(name,null,null);????

8.? ???}????

9.? ...????

10. ???public?Object?getBean(String?name,Class?requiredType,Object[]?args)throws?BeansException{????

11. ??????//對傳入的Bean?name稍做處理,防止傳入的Bean?name名有非法字符(或則做轉(zhuǎn)碼)????

12. ??????String?beanName=transformedBeanName(name);????

13. ??????Object?bean=null;????

14. ??????//手工檢測單例注冊表????

15. ??????Object?sharedInstance=null;????

16. ??????//使用了代碼鎖定同步塊,原理和同步方法相似,但是這種寫法效率更高????

17. ??????synchronized(this.singletonCache){????

18. ?????????sharedInstance=this.singletonCache.get(beanName);????

19. ???????}????

20. ??????if(sharedInstance!=null){????

21. ?????????...????

22. ?????????//返回合適的緩存Bean實例????

23. ?????????bean=getObjectForSharedInstance(name,sharedInstance);????

24. ??????}else{????

25. ????????...????

26. ????????//取得Bean的定義????

27. ????????RootBeanDefinition?mergedBeanDefinition=getMergedBeanDefinition(beanName,false);????

28. ?????????...????

29. ????????//根據(jù)Bean定義判斷,此判斷依據(jù)通常來自于組件配置文件的單例屬性開關????

30. ????????//<bean?id="date"?class="java.util.Date"?scope="singleton"/>????

31. ????????//如果是單例,做如下處理????

32. ????????if(mergedBeanDefinition.isSingleton()){????

33. ???????????synchronized(this.singletonCache){????

34. ????????????//再次檢測單例注冊表????

35. ?????????????sharedInstance=this.singletonCache.get(beanName);????

36. ?????????????if(sharedInstance==null){????

37. ????????????????...????

38. ???????????????try?{????

39. ??????????????????//真正創(chuàng)建Bean實例????

40. ??????????????????sharedInstance=createBean(beanName,mergedBeanDefinition,args);????

41. ??????????????????//向單例注冊表注冊Bean實例????

42. ???????????????????addSingleton(beanName,sharedInstance);????

43. ???????????????}catch?(Exception?ex)?{????

44. ??????????????????...????

45. ???????????????}finally{????

46. ??????????????????...????

47. ??????????????}????

48. ?????????????}????

49. ???????????}????

50. ??????????bean=getObjectForSharedInstance(name,sharedInstance);????

51. ????????}????

52. ???????//如果是非單例,即prototpye,每次都要新創(chuàng)建一個Bean實例????

53. ???????//<bean?id="date"?class="java.util.Date"?scope="prototype"/>????

54. ???????else{????

55. ??????????bean=createBean(beanName,mergedBeanDefinition,args);????

56. ???????}????

57. }????

58. ...????

59. ???return?bean;????

60. }????

61. }?????

剛才的源碼中,大家真正要記住的是Spring對bean實例的創(chuàng)建是采用單例注冊表的方式進行實現(xiàn)的,而這個注冊表的緩存是HashMap對象,如果配置文件中的配置信息不要求使用單例,Spring會采用新建實例的方式返回對象實例.

后面一段是判定是否為socpe為singleton,是的話執(zhí)行單例模式的過程,只創(chuàng)建一個新的對象,否的話則可以創(chuàng)建多個對象。

?

總結

以上是生活随笔為你收集整理的框架:spring总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。