注册与实例化bean
通常在resource目录下创建以application开头的xml作为bean的元数据属性配置,通过定义来管理bean的注册和实例化。
set方法
<!-- 一个bean标签就表示一个对象, id:这个对象的唯一标识, name:类似别名, class:注册对象的完全限定名 -->
<!-- 使用setter注入,绑定方法名setXXX,name属性值必须与XXX一致,并且setter方法必须为public -->
<!-- 通过setter注入,实际是通过反射调用类的无参构造,所以在显示为类定义构造方法的时候不要忘记添加一个无参构造 -->
<bean id="person1" name="person" class="com.nanborone.bean.Person">
<!-- 使用property标签给对象的属性赋值, name:表示属性的名称, value:表示属性的值 -->
<property name="id" value="1"/>
<property name="name" value="nanborone"/>
<property name="male" value="true"/>
</bean>
构造方法
<!-- 使用constructor注入,绑定构造方法形参名XXX,name属性值必须与XXX一致 -->
<!-- constructor-arg个数必须与已有的构造器参数个数相同 -->
<bean id="person2" class="com.nanborone.bean.Person">
<!-- 使用constructor-arg标签在对象构造的时候给属性赋值, name:表示属性的名称, value:表示属性的值 -->
<!-- 在使用构造器赋值的时候可以省略name属性,但是此时就要求必须严格按照构造器参数的顺序来填写了 -->
<!-- 如果name属性省略且有相同参数个数的构造器,后定义的会覆盖先定义的除非指定type来匹配确定的构造器 -->
<constructor-arg name="id" value="2"/>
<constructor-arg name="name" value="nanborone"/>
<constructor-arg name="male" value="true"/>
</bean>
<bean id="person3" class="com.nanborone.bean.Person">
<!-- 如果想不按照顺序来添加参数值,那么可以搭配index属性来使用 -->
<constructor-arg value="3"/>
<constructor-arg value="true" index="2"/>
<constructor-arg value="nanborone" index="1"/>
</bean>
<bean id="person4" class="com.nanborone.bean.Person">
<!-- 可以使用type属性来指定类型,但是无法自动拆装箱,可以用type="int" -->
<constructor-arg value="4" type="int"/>
<constructor-arg value="nanborone" type="java.lang.String"/>
<constructor-arg value="true" index="2"/>
</bean>
Spring也可以将String转成默认的Java内置类型。例如int
, long
, String
, boolean
等,通过StringToXXXConverter 。
通常情况下我们只使用最简单的属性注入方式,最简单的构造器注入偶尔也会使用,剩下的加乱七八糟属性的基本不用。
工厂模式
在之前的案例中,所有bean对象的创建都是通过反射得到对应的bean实例,其实在spring中还包含另外一种创建bean实例的方式,就是通过工厂模式进行对象的创建。
<!-- 静态工厂:不需要创建工厂类实例,通过类方法(静态方法)来获得bean -->
<!-- class:指定静态工厂类, factory-method:指定哪个方法是工厂方法 -->
<bean id="person1" class="com.nanborone.bean.factory.PersonStaticFactory" factory-method="getInstance">
<!--constructor-arg:可以为方法指定参数-->
<constructor-arg value="nanborone" />
</bean>
<!-- 实例工厂:需要先创建工厂类实例,再通过实例调用实例方法来获得bean-->
<bean id="personInstanceFactory" class="com.nanborone.bean.factory.PersonInstanceFactory" />
<!-- factory-bean:指定使用哪个工厂实例, factory-method:指定使用哪个工厂实例的方法 -->
<bean id="person2" class="com.nanborone.bean.Person" factory-bean="personInstanceFactory" factory-method="getInstance">
<constructor-arg value="nanborone" />
</bean>
创建对应的静态工厂类和实例工厂类:
public class PersonStaticFactory {
public static Person getInstance(String name) {
return new Person(1, name, true);
}
}
public class PersonInstanceFactory {
public Person getInstance(String name) {
return new Person(1, name, true);
}
}
FactoryBean
FactoryBean是Spring规定的一个接口,当前接口的实现类,Spring都会将其作为一个工厂,但是在Ioc容器启动的时候不会创建实例,只有在使用的时候才会创建对象,无论是不是单例的。
<bean id="myFactoryBean" class="com.nanborone.bean.factorybean.MyFactoryBean" />
创建MyFactoryBean类:
public class MyFactoryBean implements FactoryBean<Person> {
// 工厂方法,返回需要创建的对象
@Override
public Person getObject() throws Exception {
System.out.println("通过MyFactoryBean创建");
return new Person(1, "nanborone, true);
}
// 返回创建对象的类型,spring会自动调用该方法返回对象的类型
@Override
public Class<?> getObjectType() {
return Person.class;
}
// 创建的对象是否是单例对象
@Override
public boolean isSingleton() {
return false;
}
}
测试的时候需要通过myFactoryBean来获得person实例
public class IocTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
Person person = context.getBean("myfactorybean", Person.class);
System.out.println(person);
}
}