本文基於Spring5.05
官網地址:https://projects.spring.io/sp...java
AnnotationConfigApplicationContext | 一個或多個Java配置類加載Spring應用上下文 |
AnnotationConfigWebApplicationContext | 一個或多個Java配置類加載Spring Web應用上下文 |
ClassPathXmlApplicationContext | 從類路徑下的一個或多個XML配置文件加載上下文,把應用上下文的定義文件做爲類資源 |
FileSystemXmlApplicationContext | 從文件系統下的一個或多個XML配置文件加載上下文 |
XmlWebApplicationContext | 從Web應用下的一個或多個XML配置文件加載上下文 |
GenericApplicationContext | 以可刷新的方式讀取不一樣bean定義格式加載上下文 |
實例化 | Spfing對Bean進行實例化 |
填充屬性 | Spring將值和bean的引用注入到bean對應的屬性中 |
BeanNameAware 的 SetBeanName() | 若是Bean實現了BeanNameAware接口,Spring將bean的id傳遞給SetBeanNamer()方法 |
BeanFactoryAware 的 setBeanFactory() | 若是Bean實現了BeanFactoryAware,Spring將調用setBeanFactory()方法,將BeanFactory容器實例傳入 |
ApplicationContextAware 的 setApplicationContext() | 若是Bean實現了ApplicationContextAware,Spring將調用setBeanFactory()方法,將BeanFactory容器實例傳入 |
BeanPostProcess 的 postProcessBeforeInitialization() | - |
InitializingBean 的 afterPropertiesSet() 和自定義初始方法 | @PostConstruct -> InitializingBean -> init-method |
BeanPostProcess 的 postProcessAfterInitialization() | - |
已完成Bean的初始化,使用Bean直至容器關閉 | - |
DisposableBean 的 destory()方法 和自定義銷燬方法 | @PreDestory -> DisposableBean -> destory-method |
1)組件掃描(compoent sacnning):Spring會自動發現應用上下文所建立的bean
2)自動裝配(autowiring):Spring自動知足bean之間的依賴
實現自動化配置一般是在Java類中聲明註解,並經過組件掃描使指定範圍內的註解生效的一種方式正則表達式
元素 | 父元素 | 屬性 | 說明 |
<bean> 聲明Bean定義 |
<beans> | id | 惟一標示 |
name | 名稱,多個用','隔開,不能與已有id重複 | ||
class | 指定實例類型 | ||
scope | 單例/多例 | ||
lazy-init | 懶加載 | ||
autowire | 自動裝配策略 | ||
autowire-candidate | 是否參與自動注入 | ||
primary | 優先注入 | ||
depends-on | 依賴指定bean | ||
init-method | 自定義初始化方法 | ||
destroy-method | 自定義銷燬方法 | ||
abstract | 抽象類,是則不建立對象 | ||
parent | 指定父類Bean,繼承父類屬性值 | ||
factory-bean | 指定工廠Bean | ||
factory-method | 指定工廠方法 | ||
<alias> 聲明Bean的別名 |
<beans> | name | 指定Bean |
alias | 別名 | ||
<property> 經過Setter方法初始化Bean (可以使用P-命名空間代替) |
<bean> | name | 指定屬性名,以setName()形式 |
ref | 給引用類型指定bean | ||
value | 給基本類型賦值 | ||
<constructor-arg> 經過構造器方法初始化Bean (spring3.0後可以使用c-命名空間代替) |
<bean> | index | 構造方法參數索引,從0開始 |
type | 構造方法參數類型,會有歧義 | ||
name | 構造方法參數名稱 | ||
ref | 引用類型指定bean | ||
value | 基本類型賦值 | ||
<set>/<List> 聲明集合 |
<constructor-arg>/<property> | 注入參數爲集合時使用(c/p-命名空間沒法裝配集合) | |
<ref> 聲明集合元素 |
<set>/<List> | bean | 指定Bean定義 |
<value> 聲明集合元素 |
<set>/<List> | <value>val</value> | 指定集合字面量元素值 |
util-命名空間 | <beans> | <util:constant> | 應用某個類型的public static域,並將其暴露爲bean |
<util:list> | 建立一個java.util.List類型的bean,其中包含值與引用 | ||
<util:set> | 建立一個java.util.Set類型的bean,其中包含值與引用 | ||
<util:map> | 建立一個java.util.Map類型的bean,其中包含值與引用 | ||
<util:properties> | 建立一個java.util.properties類型的bean | ||
<util:property-path> | 應用某個類型的public static域,並將其暴露爲bean | ||
<import> | 引入新的xml配置 |
Ps:關於p/c-命名空間,添加xml配置後,在bean中做爲屬性使用
語法:p:屬性名[-ref]="字面量或BeanId"
屬性名可設置爲 name(參數名)、_0(參數下標,從0開始)、_(只有一個參數時可以使用)spring
註解 | 說明 | 屬性 | 屬性說明 |
@Bean | 聲明Bean定義,定義在方法上,Bean的Id默認爲方法名 | value/name | 指定Bean的Id |
autowire | 指定自動注入策略,默認爲NO | ||
initMethod | 指定自定義初始化方法 | ||
destroyMethod | 指定自定義銷燬方法 | ||
@Scope | 指定做用域 | value/scopeName | 設置單例、多例等做用域 |
proxyMode | 設置動態代理模式,JDK、cglib等 | ||
@Import | 導入新的Java配置類 | value | 指定要導入的Java配置類,可設置單個(a.class)或數組({a.class,b.class}) |
@ImportResource | 導入新的XML配置 | value | 指定導入XML配置路徑,可爲單個("a.xml")或數組({"a.xml","b.xml"}) |
@PropertySource | 導入新的properties文件 | value | 指定導入properties文件路徑,可爲單個("a.properties")或數組({"a.properties","b.properties"}) |
註解 | 說明 | 屬性 | 屬性說明 |
@Configuration | 聲明配置類,Spring會從配置類中加載上下文 | value | |
@Component | 聲明組件,同@Controller,@Service... | value | 指定Bean的Id,也可經過@Named聲明Id(jsr330) |
@Autowired | 可修飾類變量、set方法,以ByType方式自動注入組件,同@Resource(jsr250),@Inject(jsr330) | required | 默認true,未找到注入的Bean會報錯,false關閉,關閉時注意NullPointerException |
@Qualifier | 與Autowired配置使用,指定Bean的Id注入 | value | 指定Bean的Id |
@ComponentScan | 啓用組件掃描,也可在XML中配置<context:component-scan> | basePackages | 指定掃描包,可接受單個包名("com.*")和數組{"service","controller"},不安全,重構代碼修改包結構會出現問題 |
basePackageClasses | 指定類所在的包做爲組件掃描的基礎包。可經過在須要導入的包中建立並指定Marker interface空接口 |
在Spring3.1中,Spring引入了bean profile的功能,要使用profile,將全部不一樣的bean定義整理到一個或多個profile之中,在將應用部署到每一個環境時,要確保對應的profile處於激活(active)的狀態。沒有指定profile的bean始終會被建立數組
@Profile()
在Spring3.1中,只能在類級別上使用@Profile註釋,與@Configuration配合使用
在Spring3.2開始,能夠再方法級別上使用,與@Bean註解一同使用安全
在<beans>中聲明profile屬性
可在<beans>中嵌套聲明<beans> 實現多個profile共存一個xml文檔session
spring.profiles.active 設置激活的profile
spring.profiles.default active未設置則默認爲default值dom
Spring4引入@Conditional註解
可使用到帶有@Bean註解的方法上。若是給定的條件爲true,就會建立這個Bean,不然忽略。post
@Conditional能夠指定任意實現Condition接口的類型,
並實現boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata)返回true則建立Bean測試
檢查帶有@Bean註解的方法上還有什麼其餘註解
isAnnotatrd() 指定註解是否存在
getAnnotationAttributes 等獲取註解集合ui
spring4開始,Profile註解進行重構,使其基於@conditional和Condition實現。
僅有一個Bean匹配所需的結果時,自動裝配纔是有效的。
若是不只有一個bean可以匹配結果的話,這種歧義性會阻礙Spring自動裝配屬性、構造器參數或方法參數。
單例(singleton): 在整個應用中,只會建立bean的一個實例(默認)
原型(prototype):每次注入或經過Spring應用上下文獲取的時候,都會建立一個新的bean實例。
會話(session) :在Web應用中,爲每一個會話建立一個bean實例
請求(request) :在Web應用中,爲每一個請求建立一個bean實例
Java配置:使用 @Scope 註解聲明做用域,能夠與@Component 或 @Bean一塊兒使用
XML配置:<bean scope="singleton">
可經過ConfigurableBeanFactory.SCOPE_PROTOTYPE 或 SCOPE_SINGLETON 指定
也可用WebApplicationContext.SCOPE_SESSION等(須要在Web應用中使用)
@Scope 還有一個proxyMode 能夠設置動態代理模式(經過ScopedProxyMode 枚舉類來設置JDK、cglib等)
在XML中聲明做用域代理:<bean><aop:scoped-proxy ></bean>默認是cglib
可經過設置proxy-target-class=false 更改成JDK代理
1)屬性佔位符(Property placeholder)
2) Spring表達式語言(SpEL)
最簡單方式:聲明屬性源(@PropertySource導入資源)並經過Spring的Environment來檢索屬性
@Autowired
Environment env;
String getProperty(String key)
String getProperty(String key, String defaultValue)
T getProperty(String key, Class<T> type)
T getProperty(String key, Class<T> type, String defaultValue)
String getRequiredProperty(String key)
T getRequiredProperty(String key, Class<T> type)
boolean containsProperty(String var1)
Class<T> getPropertyAsClass(String key, Class<T> type)
String[] getActiveProfiles(); 獲取激活的profiles
String[] getDefaultProfiles(); 獲取默認的profiles
boolean acceptsProfiles(String... var1); 若是environment支持給定profile的話,就返回true
在Spring裝配中,佔位符的形式爲使用"${...}"包裝的屬性名稱
在XML中使用屬性佔位符(前提是經過<context:property-placeholder location=" "/>引入資源)
<context:property-placeholder location="classpath:demo.properties"/> <bean id="demo" class="" c:_name="${demo.name}">
在Java中使用屬性佔位符(需配置一個PropertyPlaceholderConfigurer 或 PropertySourcesPlaceholderConfigurer Bean,Spring 3.1 之後推薦後者,由於其可以基於Spring Environment及其屬性源來解析佔位符)
public class Demo { @Value("${demo.name}") private String name; }
Spring3引入Spring表達式語言(Spring Expression Language,SpEL)。經過表達式,在運行時計算獲得值,實現裝配。
SpEL的形式爲"#{...}"
1) 使用Bean的Id來引用Bean
2)調用方法和訪問對象的屬性
3)對值進行算術、關係和邏輯運算
4)正則表達式匹配
5)集合操做
除依賴注入,Spring Security支持SpEL定義安全限制規則;Thymeleaf模板支持SpEL引用模型數據
列子:
//獲取當前時間的毫秒值,T()表達式會將java.lang.System視爲Java中對應的類,並調用其靜態方法currentTimeMills() #{T(System).currentTimeMills()} //獲取Id爲demo的Bean,並引用其name屬性(應該是經過get方法獲取的吧!未驗證) #{demo.name} //經過systemProperties對象引用系統屬性 #{systemProperties['disc.title']}
//1)表示字面值 #{3.14159} #{9.87E4} #{'demo'} #{false} //true和false的計算結果就是它們對應的Boolean類型的值 //2)引用bean、屬性和方法 #{demo} //獲取Id爲demo的Bean的引用 #{demo.name} //獲取Id爲demo的Bean的name屬性值 #{demo.getName()} #{demo.getName().toUpperCase()} #{demo.getName()?.toUpperCase()} //避免getName()返回null,出現NullPointException,使用'?.'類型安全的運算符,若是getName()返回null,則不會調用toUpperCase(),表達式返回null //3)在表達式中使用類型(依賴T()這個關鍵的運算符,其真正價值在於訪問目標類型的靜態方法和常量) #{T(java.lang.Math)} //表示Math的class對象引用 #{T(java.lang.Math).PI} #{T(java.lang.Math).random()} //4)SpEL運算符 //算數運算:+ - * / % ^ //比較運算:< > == <= >= lt gt eq le ge //邏輯運算:and or not //條件運算:?:(ternary) ?:(Elvis) //正則匹配:matches #{2 * T(java.lang.Math).PI * cricle.radius} #{T(java.lang.Math).PI * cricle.radius ^ 2} //^ 是用於乘方計算的運算符 #{demo.name + 'and' + demo.realname} //使用String類型的值,+ 爲鏈接符 #{demo.age == 20} #{demo.age eq 20} //比較運算符有兩種形式:符號形式和文本形式,二者等同,計算結果爲Boolean值 #{demo.name != null ? demo.name : "roylion"} //三元運算符的一個常見場景:檢查null值,並用一個默認值替代null #{demo.name ?: "roylion"} //此三元運算符一般稱爲Elvis運算符,用來簡化上述場景。 #{demo.emial matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.com'} //匹配正則表達式 //5)計算集合 #{demo.books[4].title} #{demo.books[T(java.lang.Math).random() * demo.books.size()].title} //[] 運算符能夠從集合或數組中按照索引獲取元素,甚至String(基於0開始) #{'Im a big handsome '[3]} //.?[...] 對集合進行過濾,獲得集合的一個子集, //[]中接受另外一個表達式,當SpEL迭代書本列表時,會對每一本書計算這個表達式,若是爲true,則會存放到新的集合中 #{demo.books.?[title eq 'springInAction']} #{demo.books.^[title eq 'springInAction']} //.^[] 查詢第一個匹配項 #{demo.books.$[title eq 'springInAction']} //.$[] 查詢最後一個匹配項 #{demo.books.![title]} //.![] 從集合每一個成員中選擇特定的屬性放到另一個集合中
保持SpEL表達式的簡潔,儘可能不要寫複雜的SpEL表達式。由於SpEl表達式是String類型,測試困難