IoC容器的构建方式
(1)基于XML配置方式(可以开启注释配置,通过注释配置Bean和装配工作)
(2)基于Goovy脚本配置方式(DSL)
(3)基于Java Config配置注解方式(通过Configuration和Bean注释)
下面将讲解基于XML配置方式来构建IoC容器
1 Bean的实例化方法(三种)
1.1 构造方法实例化
下面这种方法是默认类需要一个无参构造,其中的id是Bean的配置属性,用来标识一个Bean
<!-- Bean实例化 -->
<!-- 构造方法实例化 -->
<!-- 无参构造(默认) -->
<bean id="exampleBean" class="com.lxy.springcore.ExampleBean"/>
下面这种方法中是在类中创建了一个有参构造,需要添加一个constructor-arg
<!-- 有参构造 -->
<bean id="exampleBean2" class="com.lxy.springcore.ExampleBean2">
<constructor-arg value="hello Spring"/>
</bean>
1.2 静态工厂方法实例化
静态工厂方法就是通过一个类的静态工厂方法来创建Bean
//静态工厂方法实例化
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService(){}
public static ClientService getInstance()
{
return clientService;
}
}
<!-- 静态工厂方法实例化 -->
<!-- 需要在最后使用 factory-method 参数 -->
<bean id="clientService" class="com.lxy.springcore.ClientService" factory-method="getInstance"/>
1.3 实例工厂方法实例化
实例工厂方法实例化创建是通过已经在容器中的Bean通过方法实例化一个新的Bean
//实例工厂方法实例化
public class DefaultClientServiceLocator {
public ClientService getClientService()
{
return ClientService.getInstance();
}
}
<!-- 实例工厂方法实例化 -->
<!-- 先将基本信息写完 -->
<!-- 再写 factory-bean 和 factory-method -->
<bean id="defaultClientServiceLocator" class="com.lxy.springcore.DefaultClientServiceLocator"/>
<bean id="clientService2" factory-bean="defaultClientServiceLocator" factory-method="getClientService"/>
2 Bean的依赖装配方式
2.1 通过构造方法参数装配的方式(四种)
2.1.1 Bean引用
<!-- Bean的引用 -->
<bean id="bar" class="com.lxy.springcore.Bar"/>
<bean id="baz" class="com.lxy.springcore.Baz"/>
<bean id="foo" class="com.lxy.springcore.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
</bean>
2.1.2 根据参数类型
public class ExampleBean3 {
private final int age;
private final String name;
public int getAge() {
return age;
}
public String getName() {
return name;
}
public ExampleBean3(int age, String name) {
this.age = age;
this.name = name;
}
}
<!-- 构造方法参数类型 -->
<bean id="exampleBean3" class="com.lxy.springcore.ExampleBean3">
<constructor-arg type="int" value="20"/>
<constructor-arg type="java.lang.String" value="LXY"/>
</bean>
2.1.3 根据参数位置
如果构造方法有两个相同类型的参数时,可以使用index来设置依赖顺序,indeks是基于0开始的
<!-- 构造方法参数位置 -->
<bean id="exampleBean32" class="com.lxy.springcore.ExampleBean3">
<constructor-arg index="0" value="21"/>
<constructor-arg index="1" value="LWW"/>
</bean>
2.1.4 根据参数名称
<!-- 构造方法参数名称 -->
<bean id="exampleBean33" class="com.lxy.springcore.ExampleBean3">
<constructor-arg name="age" value="22"/>
<constructor-arg name="name" value="LWZ"/>
</bean>
2.2 Setter方法装配
容器在调用无参构造方法或者无参工厂实例化Bean方法之后,调用Setter方法完成属性的装配
public class ComplexShape {
private Shape shape;
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
@Override
public String toString() {
return "ComplexShape{" +
"shape=" + shape +
'}';
}
}
<!-- Setter方法装配 -->
<bean id="complexShape" class="com.lxy.springcore.ComplexShape">
<property name="shape" ref="rectangle"/>
</bean>
<bean id="rectangle" class="com.lxy.springcore.common.impl.Rectangle">
<constructor-arg index="0" value="1"/>
<constructor-arg index="1" value="2"/>
</bean>
3 Bean的具体配置
3.1 直接赋值
直接赋值是针对基本数据类型和String类型,可以配置properties元素和value属性来指定属性或者构造方法参数赋值
<!-- 直接赋值 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/memo"/>
<property name="username" value="root"/>
<property name="password" value="523399"/>
<property name="maxTotal" value="20"/>
</bean>
3.2 idref属性
<!-- idref -->
<bean id="idRefExample" class="com.lxy.springcore.IdRefExample">
<constructor-arg>
<idref bean="bar"/>
</constructor-arg>
</bean>
idref VS ref
idref装配的是目标bean的id而不是目标bean的实例,同时使用idref容器在部署的时候还会验证这个名称的bean是否真实存在,其实idref就跟value一样,只是将某个字符串装配到属性或者构造函数中,只不过装配的是某个Bean定义的id属性值
ref是将目标函数Bean定义的实例装配到属性或构造函数中
3.3 内部Bean
定义在<property/>内部的<bean/>元素称为内部bean
<!-- 内部Bean -->
<bean id="foo3" class="com.lxy.springcore.Foo">
<constructor-arg>
<bean class="com.lxy.springcore.Bar"/>
</constructor-arg>
<constructor-arg>
<bean class="com.lxy.springcore.Baz"/>
</constructor-arg>
</bean>
3.4 Collection
使用<list/>,<set/>,<map/>,<props/>元素可以设置Java的集合类型的属性和参数
注:在使用集合元素时,集合的value可以使用bean,ref,idref,list,set,map,props,value,null
public class ComplexObject {
private Properties properties;
private List<Object> list;
private Set<String> set;
private Map<String,Object> map;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
@Override
public String toString() {
return "ComplexObject{" +
"properties=" + properties +
", list=" + list +
", set=" + set +
", map=" + map +
'}';
}
}
<!-- Collection -->
<bean id="complexObject" class="com.lxy.springcore.ComplexObject">
<property name="properties">
<props>
<prop key="zhangsan">[email protected]</prop>
<prop key="lisi">[email protected]</prop>
</props>
</property>
<property name="list">
<list>
<value>Java</value>
<ref bean="foo2"/>
<ref bean="foo3"/>
<value>20</value>
</list>
</property>
<property name="map">
<map>
<entry key="zhangsan" value="[email protected]"/>
<entry key="lisi" value-ref="foo3"/>
</map>
</property>
<property name="set">
<set>
<value>20</value>
<value>C++</value>
<value>javaScript</value>
</set>
</property>
</bean>
3.5 null和空字符串
<!-- null 和 空字符串 -->
<bean id="exampleBean4" class="com.lxy.springcore.ExampleBean4">
<property name="name">
<null/>
</property>
<property name="email" value=""/>
</bean>