你可以以定义属性和构造参数来引用其他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