Spring框架是以 簡化Java EE應用程序的開發 爲目標而建立的。Spring能夠實現不少功能,可是這些功能的底層都依賴於它的兩個核心特性,也就是依賴注入和麪向切面編程。幾乎Spring所作的任何事情均可以追溯到下述的一條或多條策略:java
基於POJO的輕量級和最小侵入性編程;
經過依賴注入和麪向接口實現鬆耦合;
基於切面和慣例進行聲明式編程;
經過切面和模板減小樣板式代碼。 正則表達式
Spring的三個基本願景:spring
使用DI來實現低耦合
使用AOP切面實現高內聚
使用模板消除樣板式代碼,好比jdbcTemplate編程
容器是Spring框架的核心。Spring容器使用DI管理構成應用的組件(Bean),它會建立相互協做的組件之間的關聯。毫無疑問,這些對象更簡單幹淨,更易於理解和重用,更易於單元測試。session
Spring爲每一個Bean定義了多種做用域,默認都是以單例的模式建立的:app
單例(Singleton):在整個應用中,只建立bean的一個實例。
原型(Prototype):每次注入或者經過Spring應用上下文獲取的時候,都會建立一個新的bean實例。
會話(Session):在Web應用中,爲每一個會話建立一個bean實例。
請求(Rquest):在Web應用中,爲每一個請求建立一個bean實例。框架
Bean的生命週期:ide
Bean實例生命週期的執行過程以下:post
Spring對bean進行實例化,默認bean是單例;
Spring對bean進行依賴注入;
若是bean實現了BeanNameAware接口,spring將bean的id傳給setBeanName()方法;
若是bean實現了BeanFactoryAware接口,spring將調用setBeanFactory方法,將BeanFactory實例傳進來;
若是bean實現了ApplicationContextAware接口,它的setApplicationContext()方法將被調用,將應用上下文的引用傳入到bean中;
若是bean實現了BeanPostProcessor接口,它的postProcessBeforeInitialization方法將被調用;
若是bean實現了InitializingBean接口,spring將調用它的afterPropertiesSet接口方法,相似的若是bean使用了init-method屬性聲明瞭初始化方法,該方法也會被調用;
若是bean實現了BeanPostProcessor接口,它的postProcessAfterInitialization接口方法將被調用;
此時bean已經準備就緒,能夠被應用程序使用了,他們將一直駐留在應用上下文中,直到該應用上下文被銷燬;
若bean實現了DisposableBean接口,spring將調用它的distroy()接口方法。一樣的,若是bean使用了destroy-method屬性聲明瞭銷燬方法,則該方法被調用;單元測試
Spring自帶了多種類型的上下文(適用於在普通類中利用Spring的上下文加載須要的Bean):
AnnotationConfigApplicationContext:從一個或者多個的Java配置類中加載Spring的應用上下文
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
AnnotationConfigWebApplicationContext:從一個或多個基於Java的配置類中加載Spring Web應用上下文。
ClassPathXmlApplicationContext:從類路徑下的一個或多個XML配置文件中加載上下文定義,把應用上下文的定義文件做爲類資源。
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");
FileSystemXmlapplicationcontext:從文件系統下的一個或多個XML配置文件中加載上下文定義。
XmlWebApplicationContext:從Web應用下的一個或多個XML配置文件中加載上下文定義。
一、@Component 代表該類會做爲組件類,並告知Spring 要爲這個類建立bean(這個bean的ID默認取名類名的首字母小寫)。不過組件掃描默認是不啓用的。咱們還須要顯示配置一下Spring,從而命令他去尋找帶有@Component(相似的還有@Repository @service @controller)註解的類,併爲他建立bean。有三種方式來配置Spring建立Bena:
* 自動化裝配的方式:一、建一個配置類。@Configuration 代表這個類是一個配置類 加上@ComponentScan(basePackages={"包名1","包名2"} 或者 basePackageClasses={包1的某個Class,包2的某個Class}) 會掃描和配置類相同的包,以及這個包下的全部子包。
二、Spring XML配置方式: <context:component-scan base-package=""/>
* 在JavaConfig中進行顯示配置(適用於第三方的類庫組件裝配到本身應用中)
@Configuration public class JavaConfig { @Bean(name = "base64Util") public Base64Util getBase64Util(){ return new Base64Util(); } @Bean(name = "base64UtilExpand") //這種顯示配置默認的Bean名是方法名。因此最好顯示配置一下 public Base64UtilExpand getBase64UtilExpand(){ //對於這種建立的bean須要引用其餘的bean。Spring是這樣處理的:當引用到還沒建立的bean的時候,Spring會攔截下這個引用,等到引用的bean的建立完成。已保證Spring bean的單例模式. return new Base64UtilExpand(getBase64Util()); } @Bean(name = "base64UtilExpand") public Base64UtilExpand getBase64UtilExpand(Base64Util base64Util){ return new Base64UtilExpand(base64Util); } }
* 在XML中進行顯示配置,最古老的方式,通常不多用,有兩種方式注入,構造器注入和set注入:
<!--構造器注入--> <bean id="cDPlayer" class="com.CDPlayer"> <constructor-arg ref="compactDisc"> </bean> <bean id="cDPlayer" class="com.CDPlayer"> <constructor-arg value="compactDisc"> </bean> <bean id="cDPlayer" class="com.CDPlayer"> <constructor-arg> <list> <value></value> </list> </constructor-arg> </bean> <!--setter注入--> <bean id="cDPlayer" class="com.CDPlayer"> <property name="compactDisc" ref="compactDisc"> </bean> <bean id="cDPlayer" class="com.CDPlayer"> <property name="compactDisc" value="compactDisc"><!--裝配字面量:--> </bean> 裝配集合 <bean id="cDPlayer" class="com.CDPlayer"> <property name="compactDisc" value="compactDisc"> <property name=""> <list> <value></value><!--裝配集合--> </list> </property> </bean>
二、@scope 指定bean建立時的做用域,Spring默認建立單例模式的bean。但也有特殊的狀況,這裏須要說明的是若是某個類注入了Session 和 Request 做用域的Bean,由於這個Bean是在用戶請求的時候產生的,在Spring 運行起來的時候並不存在。這裏Spring是這樣處理的:注入給對應Bean的一個代理,而當用戶請求產生session 或者 request 做用域Bean的時候,由這個代理鏈接到相應的Bean處理請求...
單例(一個應用建立一個實例):@Scope(value=ConfigurableBeanFactory.SCOPE_SINGLETON)
請求(一個請求建立一個實例):@Scope(value=WebApplicationContext.SCOPE_REQUEST,proxyMode = ScopedProxyMode.INTERFACES)
原型(一次注入建立一個實例):@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
會話(一次會話建立一個實例):
(接口)@Scope(value = WebApplicationContext.SCOPE_SESSION,proxyMode = ScopedProxyMode.INTERFACES)
(具體類)@Scope(value = WebApplicationContext.SCOPE_SESSION,proxyMode = ScopedProxyMode.TARGET_CLASS)
全局會話(全局會話建立一個實例):@Scope(value=WebApplicationContext.SCOPE_GLOBAL_SESSION)
固然也能夠在XML中配置:
<bean id="shoppingCart2" class="com.entity.ShoppingCart2" scope="session"> <aop:scoped-proxy proxy-target-class="false"/> </bean>
三、限定符(用的較少)
@Profile 決定哪些bean能夠被激活。須要注意的是沒有指定profile的bean始終都會被建立,與激活哪一個profile沒有關係。
@Conditional中給定了一個Class,這個Class 實現了Codition 接口的matches 方法,該方法返回true 則生成bean,不然不生成。
@primary 常見的狀況是一個接口僅有一個實現類,因此使用@Autowire的後,Spring能夠走到對應的實現類。若是一個接口有多個實現類呢?@Component 和 @primary 同時使用,標註哪一個實現類優先被使用。
@Qualifier 使用@primary 仍然沒法保證哪一個bean被選擇,由於能夠在多個實現類上使用@primary。因此能夠在實現類用@Qualifter("bean")名指定bean的名字。並在@Autowire 注入接口的時候是使用Qualifier 指定實現類的bean名。固然,也能夠用@Resource(name=" ")指定類的名稱。
四、讀取 properties 文件
(1) @PropertySource 會引用一個類路徑上的properties的文件,並利用Environment類獲取properties的變量值。例如:@PropertySource("classpath:mongo.properties")
@Configuration @PropertySource("classpath:mongo.properties") public class JavaConfig { @Bean(name = "mongoUtil") public MongoUtil getMongoUtil(Environment env){ return new MongoUtil(env.getProperty("mongo.host"), env.getProperty("mongo.port"), env.getProperty("mongo.database"), env.getProperty("mongo.username"), env.getProperty("mongo.password")); } }
(2) 佔位符
Spring 中佔位符的形式是使用${}的方式。在代碼文件中咱們可使用@Value註解將配置文件的值注入到變量中。爲了使用佔位符,咱們必須配置一個PropertySourcesPlaceholderConfigurer 的類,已生成相關的bean,或者經過XML配置讓Spring爲咱們自動生成:
@Configuration @PropertySource("classpath:mongo.properties") public class JavaConfig { @Bean(name = "propertySourcesPlaceholderConfigurer") public PropertySourcesPlaceholderConfigurer getPropertySourcesPlaceholderConfigurer(){ return new PropertySourcesPlaceholderConfigurer(); } }
或者:
<!--提供讀取配置文件可使用Spring佔位符${}--> <context:property-placeholder location="classpath:mongo.properties" file-encoding="utf-8" />
用法以下:
@RunWith(SpringJUnit4ClassRunner.class) //@ContextConfiguration(classes = JavaConfig.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class Test06 { @Value("${mongo.host}") private String host; @Test public void test06(){ System.out.println(host); } }
Spring Expression Language,簡稱SpEL,是一種很是靈活的表達式語言,擁有不少特性,包括:
使用bean的ID來引用bean;
調用方法和訪問對象的屬性;
對值進行算術、關係和邏輯運算;
正則表達式匹配;
集合操做。
SpEL 採用#{}的形式:
一、表明字面值:#{3.14} #{'Hello'} #{false}
二、引用bean、屬性、方法 #{bean} #{bean.artist} #{bean.toUpperCase()} #{bean?.toUpperCase()}(表示若是bean爲null 就返回null,不調用方法)
三、引用某個類 #{T{java.lang.Math}.PI}
四、三元表達式 #{bean.score > 1000 ? "win":"los"} 判空 #{bean.score ?: "win"}
五、正則表達式 #{bean.email matches '表達式'}
六、計算集合 #{bean.song[4].title}
查詢運算符(.?) #{bean.songs.?[artist eq 'hello']}
匹配第一個 (.^) #{bean.songs.^[artist eq 'hello']}
匹配最後一個 (.$) : #{bean.songs.$[artist eq 'hello']}
投影運算符 (.!) #{bean.songs.![title]}
<bean id="carl" class="com.springinaction.springidol.Instrumentalist"> <property name="song" value="#{kenny.song}" /> </bean>
public static class FieldValueTestBean { @Value("#{ systemProperties['user.region'] }") private String defaultLocale; public void setDefaultLocale(String defaultLocale) { this.defaultLocale = defaultLocale; } public String getDefaultLocale() { return this.defaultLocale; } }
Spring爲SpEL創造了兩種特殊的選擇屬性方式:systemEnvironment和systemProperties.
systemEnvironment包含了應用程序所在機器上的全部環境變量。
systemProperties包含了java應用程序啓動時所設置的全部屬性。
@RunWith(SpringJUnit4ClassRunner.class) //@ContextConfiguration(classes = JavaConfig.class) 加載配置類 @ContextConfiguration(locations = "classpath:applicationContext.xml") //加載配置文件 public class Test02 { @Resource(name = "iceCream") private Dessert dessert; @Test public void test02(){ dessert.sys(); } }