你可以以定義屬性和構造參數來引用其他bean,或者定義為內部值.xml的元素`<property/> `和` <constructor-arg/>`用來支持配置.
[TOC]
## Straight values (primitives, Strings, and so on)
`<property/>`元素的屬性`value`表現為字符串,spring的[conversion service](https://docs.spring.io/spring/docs/5.0.6.RELEASE/spring-framework-reference/core.html#core-convert-ConversionService-API) 會把它轉為正確的類型.
~~~xml
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- 調用 setDriverClassName(String)把值注入 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="masterkaoli"/>
</bean>
~~~
下面使用[p-namespace](https://docs.spring.io/spring/docs/5.0.6.RELEASE/spring-framework-reference/core.html#beans-p-namespace)簡寫
~~~xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mydb"
p:username="root"
p:password="masterkaoli"/>
</beans>
~~~
上面的方式很簡潔,但是在運行時容易有錯別字,建議使用帶幫助功能的IDE,如 IntelliJ IDEA 或 the Spring Tool Suite.
你還可以配置java.util.Properties實例
~~~xml
<bean id="mappings"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- java.util.Properties類型 -->
<property name="properties">
<value>
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
</value>
</property>
</bean>
~~~
### The idref element
idref元素只是一種防錯的方式,可以將容器中另一個bean的id(字符串值 - 不是引用)傳遞給`<constructor-arg />`或`<property />`元素。
~~~xml
<bean id="theTargetBean" class="..."/>
<bean id="theClientBean" class="...">
<property name="targetName">
<idref bean="theTargetBean"/>
</property>
</bean>
~~~
上面的方式和下面是等效的
~~~xml
<bean id="theTargetBean" class="..." />
<bean id="client" class="...">
<property name="targetName" value="theTargetBean"/>
</bean>
~~~
第一種方式比第二種方式更好一點,因為idref允許spring在部署的時候去校驗bean是否存在.第二種方式value只有在bean實例化是才會校驗
> idref元素的屬性local從4.0開始不再支持了.因為local不支持規則bean之外的引用,要升級到4.0,需要把屬性local改為bean.
>
元素<idref/>配置的地方帶來一個價值就是在`ProxyFactoryBean `配置的spring AOP攔截器,當指定攔截器名稱時,使用`<idref/>`避免拼寫錯誤實例的id.
## References to other beans (collaborators)
元素`<constructor-arg/>` 或 `<property/>`的子元素`<ref/>`指向了另一個bean.`<ref/>`標簽的屬性`bean`指向目標bean的id或name值.
~~~xml
<ref bean="someBean"/>
~~~
使用`parent`屬性指定引用的父容器內的bean.當你需要通過代理包裝父容器的bean時,名稱保持一致.
~~~xml
<!--父容器-->
<bean id="accountService" class="com.foo.SimpleAccountService">
</bean>
~~~
~~~xml
<!--子容器-->
<bean id="accountService" <!-- 和父容器的名字一樣 -->
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref parent="accountService"/> <!-- 引用父容器的bean -->
</property>
</bean>
~~~
## Inner beans
`<property/>` 或 `<constructor-arg/>`內部的`<bean/>`定義為內部類
~~~xml
<bean id="outer" class="...">
<!-- 在內部定義bean -->
<property name="target">
<bean class="com.example.Person"> <!-- 這是內部類 -->
<property name="name" value="Fiona Apple"/>
<property name="age" value="25"/>
</bean>
</property>
</bean>
~~~
內部類不需要定義id和name,定義了也不起作用,包括范圍也無效,內部類是匿名的且通過外部類來創建,不可能把內部類注入到其他bean里.
## Collections
元素`<list/>, <set/>, <map/>, <props/> `分別對應java的集合`List, Set, Map, Properties`
~~~xml
<bean id="moreComplexObject" class="example.ComplexObject">
<!-- 調用setAdminEmails(java.util.Properties) -->
<property name="adminEmails">
<props>
<prop key="administrator">administrator@example.org</prop>
<prop key="support">support@example.org</prop>
<prop key="development">development@example.org</prop>
</props>
</property>
<!-- 調用setSomeList(java.util.List) -->
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property>
<!-- 調用setSomeMap(java.util.Map) -->
<property name="someMap">
<map>
<entry key="an entry" value="just some string"/>
<entry key ="a ref" value-ref="myDataSource"/>
</map>
</property>
<!--調用setSomeSet(java.util.Set) -->
<property name="someSet">
<set>
<value>just some string</value>
<ref bean="myDataSource" />
</set>
</property>
</bean>
~~~
### Collection merging
spring支持集合的合并,元素`<list/>, <set/>, <map/>, <props/> `可以嵌套元素`<list/>, <set/>, <map/>, <props/> `子元素的值會覆蓋父元素的值
~~~xml
<beans>
<bean id="parent" abstract="true" class="example.ComplexObject">
<property name="adminEmails">
<props>
<prop key="administrator">administrator@example.com</prop>
<prop key="support">support@example.com</prop>
</props>
</property>
</bean>
<bean id="child" parent="parent">
<property name="adminEmails">
<!-- 在子集合上指定合并 -->
<props merge="true">
<prop key="sales">sales@example.com</prop>
<prop key="support">support@example.co.uk</prop>
</props>
</property>
</bean>
<beans>
~~~
當`child`實例化后,會擁有`parent`的屬性,并且覆蓋了`support`的值,最終為
~~~properties
administrator=administrator@example.com
sales=sales@example.com
support=support@example.co.uk
~~~
其他集合元素`<list/>, <set/>, <map/> `是類似的,注意list會有order屬性.
### Limitations of collection merging
集合合并,只能在子元素上設置,并且相同類型的才可以合并,否則會有異常.
### Strongly-typed collection
在java5之后,可以強制限制集合的允許的類型,如果bean注入強類型的集合,可以利用spring的類型轉換把集合轉成對應的類型,然后在注入bean.
~~~java
public class Foo {
private Map<String, Float> accounts;
public void setAccounts(Map<String, Float> accounts) {
this.accounts = accounts;
}
}
~~~
~~~xml
<beans>
<bean id="foo" class="x.y.Foo">
<property name="accounts">
<map>
<entry key="one" value="9.99"/>
<entry key="two" value="2.75"/>
<entry key="six" value="3.99"/>
</map>
</property>
</bean>
</beans>
~~~
## Null and empty string values
spring對待空參數或屬性是空字符串("")
~~~xml
<bean class="ExampleBean">
<property name="email" value=""/>
</bean>
~~~
上面的配置,等效如下java代碼
~~~java
exampleBean.setEmail("");
~~~
元素`<null/>`處理null值
~~~xml
<bean class="ExampleBean">
<property name="email">
<null/>
</property>
</bean>
~~~
上面配置等效如下java代碼
~~~java
exampleBean.setEmail(null);
~~~
## XML shortcut with the p-namespace
## XML shortcut with the c-namespace
## Compound property names
- 正確打開本書的姿勢
- 第一部分 Core
- 1. Ioc container
- 1.1. Introduction to the Spring IoC container and beans
- 1.2. Container overview
- 1.2.1. Configuration metadata
- 1.2.2. Instantiating a container
- 1.2.3. Using the container
- 1.3. Bean overview
- 1.3.1. Naming beans
- 1.3.2. Instantiating beans
- 1.4. Dependencies
- 1.4.1. Dependency Injection
- 1.4.2. Dependencies and configuration in detail
- 1.4.3. Using depends-on
- 1.4.4. Lazy-initialized beans
- 1.4.5. Autowiring collaborators
- 1.4.6. Method injection
- 1.5 Bean Scopes
- 1.6. Customizing the nature of a bean TODO
- 1.7. Bean definition inheritance TODO
- 1.8. Container Extension Points TODO
- 1.9. Annotation-based container configuration
- 1.9.1. @Required
- 1.9.2. @Autowired
- 1.9.3. Fine-tuning annotation-based autowiring with @Primary
- 1.9.4. Fine-tuning annotation-based autowiring with qualifiers TODO
- 1.9.5. Using generics as autowiring qualifiers TODO
- 1.9.6. CustomAutowireConfigurer TODO
- 1.10. Classpath scanning and managed components
- 1.10.1. @Component and further stereotype annotations
- 1.11. Using JSR 330 Standard Annotations TODO
- 1.12. Java-based container configuration
- 1.12.1. Basic concepts: @Bean and @Configuration
- 1.12.2. Instantiating the Spring container using AnnotationConfigApplicationContext
- 2. Resources
- 2.1. Introduction
- 2.2. The Resource interface
- 2.3. Built-in Resource implementations
- 2.3.1. UrlResource
- 2.3.2. ClassPathResource
- 2.3.3. FileSystemResource
- 2.3.4. ServletContextResource
- 2.3.5. InputStreamResource
- 2.3.6. ByteArrayResource
- 2.4. The ResourceLoader
- 2.5. The ResourceLoaderAware interface
- 2.6. Resources as dependencies
- 2.7. Application contexts and Resource paths
- 2.7.1. Constructing application contexts
- 2.7.2. Wildcards in application context constructor resource paths
- 2.7.3. FileSystemResource caveats
- 3. Validation, Data Binding, and Type Conversion
- 4. Spring Expression Language (SpEL)
- 5. Aspect Oriented Programming with Spring
- 5.1. Introduction
- 5.1.1. AOP concepts
- 5.1.2. Spring AOP capabilities and goals
- 5.1.3. AOP Proxies
- 5.2. @AspectJ support
- 5.2.1. Enabling @AspectJ Support
- 5.2.2. Declaring an aspect
- 5.2.3. Declaring a pointcut
- 5.2.4. Declaring advice
- 5.2.5. Introductions TODO
- 5.2.6. Aspect instantiation models TODO
- 5.2.7. Example
- 5.3. Schema-based AOP support TODO
- 5.4. Choosing which AOP declaration style to use TODO
- 5.5. Mixing aspect types TODO
- 5.6. Proxying mechanisms
- 5.6.1. Understanding AOP proxies
- 5.7. Programmatic creation of @AspectJ Proxies
- 5.8. Using AspectJ with Spring applications
- 5.8.1. Using AspectJ to dependency inject domain objects with Spring
- 5.8.2. Other Spring aspects for AspectJ
- 第二部分 Testing
- 第三部分 Data Access
- 1. Transaction Management
- 1.1. Introduction to Spring Framework transaction management
- 1.2 Advantages of the Spring Framework’s transaction support model
- 1.2.1. Global transactions
- 1.2.2. Local transactions
- 1.2.3. Spring Framework’s consistent programming model
- 1.3. Understanding the Spring Framework transaction abstraction
- 1.4. Synchronizing resources with transactions
- 1.4.1. High-level synchronization approach
- 1.4.2. Low-level synchronization approach
- 1.4.3. TransactionAwareDataSourceProxy
- 1.5. Declarative transaction management
- 1.5.1. Understanding the Spring Framework’s declarative transaction implementation
- 1.5.2. Example of declarative transaction implementation
- 1.5.3. Rolling back a declarative transaction
- 1.5.4. Configuring different transactional semantics for different beans
- 1.5.5. tx:advice元素的 settings
- 1.5.6. Using @Transactional
- 1.5.7. Transaction propagation
- 1.5.8. Advising transactional operations
- 1.5.9. Using @Transactional with AspectJ TODO
- 第四部分 web servlet
- 第五部分 Web Reactive
- 第六部分 Integration
- 第七部分 Languages