参考代码下载github:https://github.com/changwensir/java-ee/tree/master/spring4
一、XML 配置里的 Bean 自动装配
--Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是在 <bean> 的 autowire 属性里指定自动装配的模式
--byType(根据类型自动装配): 若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配.
--byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同.
--constructor(通过构造器自动装配): 当 Bean 中存在多个构造器时, 此种自动装配方式将会很复杂. 不推荐使用
public class Car2 {
private String brand;
private float price;
private String company;
public Car2() {
System.out.println("CarCycle'2 constructor...");
}
//....省去get,set方法
}
public class PersonAutowire {
private String name;
private Address address;
private Car2 car;
public PersonAutowire() {
}
//....省去get,set方法
}
public class Address {
private String city;
private String street;
//....省去get,set方法
}
配置文件beans-autowire.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 这里是手工装配-->
<!--抽象bean: bean的abstract属性为true的bean,这样的bean 不能被IOC容器实例化,只用来被继承配置
abstract="true"
若某一个bean的class属性没有指定,则该bean必须是一个抽象bean,也就是一个模板-->
<bean id="address" class="Spring4_IOC.bean.Address"
p:city="Beijing" p:street="DaZhongShi">
</bean>
<bean id="car2" class="Spring4_IOC.bean.Car2"
p:brand="Audi" p:company="pachira" p:price="300000"/>
<!--<bean id="person" class="Spring4_IOC.bean.PersonAutowire"
p:name="Tome" p:address-ref="address" p:car-ref="car"/>-->
<!--将上面改为自动注入
可以使用autowire属性指定自动装配的方式,
byName 根据Bean的名字!!和当前bean 的setter风格的属性名进行自动装配。
若有匹配的,则会自动装配;若无,则不会。
因为PersonAutowire类里的setCar刚好跟上面定义的bean的id为car,所以可以自动注入进来,如将改为id="car3",则car的结果为Null
-->
<bean id="person" class="Spring4_IOC.bean.PersonAutowire"
p:name="Tom" autowire="byName"/>
<!--byType 根据bean的类型!!和当前bean 的属性的类型进行自动装配,必须唯一
如果IOC容器中有1个以上的类型匹配的bean,则会异常。比如再添加一个Address的bean -->
<bean id="person2" class="Spring4_IOC.bean.PersonAutowire"
p:name="Tom" autowire="byType"/>
</beans>
测试方法
/**
* 自动装配 Bean
* byType(根据类型自动装配)
* byName(根据名称自动装配)
* constructor(通过构造器自动装配):不推荐使用
*/
@Test
public void testAutowire() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-autowire.xml");
//测试自动装配byName
PersonAutowire person = (PersonAutowire) ctx.getBean("person");
System.out.println("测试自动装配byName: " + person);
//测试自动装配byType
PersonAutowire person2 = (PersonAutowire) ctx.getBean("person2");
System.out.println("测试自动装配byType: " + person2);
}
XML 配置里的 Bean 自动装配的缺点
--•在 Bean 配置文件里设置autowire属性进行自动装配将会装配Bean的所有属性.然而,若只希望装配个别属性时,autowire属性就不够灵活了.
--•autowire属性要么根据类型自动装配,要么根据名称自动装配,不能两者兼而有之.
--•一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些
二、bean之间的继承与依赖
2-1.继承 Bean 配置
--•
Spring
允许继承
bean
的配置
,
被继承的
bean
称为父
b
ean
.
继承这个父
Bean
的
Bean
称为子
Bean
--•
子
Bean
从父
Bean
中继承配置
,
包括
Bean
的
属性配置
--•
子
Bean
也可以
覆盖
从父
Bean
继承过来的配置
--•
父
Bean
可以作为配置模板
,
也可以作为
Bean
实例
.
若只想把父
Bean
作为模板
,
可以设置
<bean>
的
abstract
属性为
true
,
这样
Spring
将不会实例化这个
Bean
--•
并不是
<bean>
元素里的所有属性都会被继承
.
比如
:
autowire
,
abstract
等
.
--•
也
可以忽略父
Bean
的
class
属性
,
让子
Bean
指定自己的类
,
而共享相同的属性配置
.
但此时
abstract
必须设为
true
2-2.依赖bean配置
--•
Spring
允许用户通过
depends-on
属性设定
Bean
前置依赖的
Bean
,前置依赖的
Bean
会在本
Bean
实例化之前创建好
--•
如果前置依赖于多个
Bean
,则可以通过逗号,空格或的方式配置
Bean
的名称
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--抽象bean: bean的abstract属性为true的bean,这样的bean 不能被IOC容器实例化,只用来被继承配置
abstract="true"
若某一个bean的class属性没有指定,则该bean必须是一个抽象bean,也就是一个模板-->
<bean id="address" class="Spring4_IOC.bean.Address"
p:city="Beijing" p:street="WuDaoKou">
</bean>
<!-- <bean id="address2" class="Spring4_IOC.bean.Address"
p:city="Beijing" p:street="DaZhongShi">
</bean>-->
<!--将上面的改为用bean 配置的继承:使用bean 的parent属性指定继承哪个bean的配置
如果下面增加p:city="Beijing~",则获取到的bean的ity是新增的这个,而不是继承的 -->
<bean id="address2" p:street="DaZhongShi" parent="address">
</bean>
<bean id="car" class="Spring4_IOC.bean.Car2"
p:brand="Audi" p:company="baidua" p:price="300000"/>
<!-- 要求再配置Person时,必须有一个关联的car! 换句话说person 这个bean依赖于Car 这个bean-->
<bean id="person" class="Spring4_IOC.bean.PersonAutowire"
p:name="Tom" p:address-ref="address" depends-on="car"/>
</beans>
/**
* bean 之间的关系:继承;依赖
*/
@Test
public void testRelation() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-relation.xml");
//测试继承
Address address = (Address) ctx.getBean("address");
System.out.println(address);
Address address2 = (Address) ctx.getBean("address2");
System.out.println(address2);
//测试依赖
PersonAutowire person = (PersonAutowire) ctx.getBean("person");
System.out.println("测试依赖: " + person);
}
三、Bean 的作用域
--•
在
Spring
中
,
可以在
<bean>
元素的
scope
属性里设置
Bean
的作用域
.
--•
默认
情况下
, Spring
只为每个在
IOC
容器里声明的
Bean
创建唯一一
个实例
,
整个
IOC
容器范围内都能共享该
实例
:
所有
后续的
getBean
()
调用和
Bean
引用都将返回这个唯一的
Bean
实例
.
该作用域被称为
singleton
,
它是所有
Bean
的默认作用域
.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!--使用bean的scope属性来配置bean的作用域
singleton:默认值,容器初始时创建bean实例,在整个容器的生命周期内只创建这一个bean.单例的
prototype:原型的,容器初始化时不创建bean的实例,而在每次请求时都创建一个新的bean实例,并返回-->
<bean id="car" class="Spring4_IOC.bean.Car2"
scope="prototype">
<property name="brand" value="Audi"/>
<property name="price" value="300000"/>
</bean>
</beans>
/**
* bean 的作用域:
* singleton:默认值,容器初始时创建bean实例,在整个容器的生命周期内只创建这一个bean.单例的
* prototype:原型的,容器初始化时不创建bean的实例,而在每次请求时都创建一个新的bean实例!!,
* 并返回WEB 环境作用域(request,sessionPojo)
*/
@Test
public void testScope() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-scope.xml");
Car2 car1 = (Car2) ctx.getBean("car");
Car2 car2 = (Car2) ctx.getBean("car");
System.out.println(car1 == car2); //默认是singleton,结果为true,如果为prototype则为false
}
四、使用外部属性文件
--•
在
配置文件里配置
Bean
时
,
有时需要在
Bean
的配置里混入
系统部署的细节信息
(
例如
:
文件路径
,
数据源配置信息等
).
而这些部署细节实际上需要和
Bean
配置相分离
--•
Spring
提供了一个
PropertyPlaceholderConfigurer
的
BeanFactory
后置处理器
,
这个处理器允许用户将
Bean
配置的部分内容外移到
属性文件
中
.
可以在
Bean
配置文件里使用形式为
${
var
}
的变量
,
PropertyPlaceholderConfigurer
从属性文件里加载属性
,
并使用这些属性来替换变量
.
--•
Spring
还允许在属性文件中使用
${
propName
}
,以实现属性之间的相互引用。
数据配置文件db.properties
user=root
password=123456
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///test
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--导入属性文件-->
<context:property-placeholder location="classpath:Spring4_IOC/db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
<property name="jdbcUrl" value="${jdbcUrl}"/>
<property name="driverClass" value="${driverClass}"/>
</bean>
</beans>
/**
* 使用外部属性文件
*/
@Test
public void testProperties() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-properties.xml");
DataSource dataSource = (DataSource) ctx.getBean("dataSource");
System.out.println(dataSource);
}