Spring4.0学习笔记004——Bean的配置二(基于XML文件)
Posted yfyzwr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring4.0学习笔记004——Bean的配置二(基于XML文件)相关的知识,希望对你有一定的参考价值。
1. bean的自动装配
Spring IOC容器可以实现Bean的自动装配,需要做的仅仅是在< bean >的autowire属性里指定自动装配的模式。
在实际的项目中一般很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些。
1-1. byName
根据属性名称进行自动装配,可以进行如下的改动。
<bean id="car" class="com.yfyzwr.spring.beans.Car"><!-- id改为car -->
<property name="brand" value="红旗"></property>
<property name="price" value="123456.78"></property>
</bean>
<bean id="Person" class="com.yfyzwr.spring.beans.Person" autowire="byName">
<property name="name" value="金三胖"></property>
<property name="age" value="30"></property>
<!-- 这里没有为car属性指定初始值 -->
</bean>
从输出结果可以得知Person类实例的car属性已经被成功赋值。
使用byName的自动装配方式,必须保证所依赖Bean的id名称和当前Bean的属性名称完全相同。
1-2. byType
根据属性类型进行自动装配,可以进行如下的改动。
<bean id="Car" class="com.yfyzwr.spring.beans.Car">
<property name="brand" value="红旗"></property>
<property name="price" value="123456.78"></property>
</bean>
<bean id="Person" class="com.yfyzwr.spring.beans.Person" autowire="byType">
<property name="name" value="金三胖"></property>
<property name="age" value="30"></property>
<!-- 这里没有为car属性指定初始值 -->
</bean>
从输出结果可以得知Person类实例的car属性已经被成功赋值
使用byType的自动装配方式,必须保证所依赖Bean的class的类型和当前Bean的属性的类型完全相同。
如果我们为相同的class配置两个(或多个)bean的话,那么byType自动装配的结果有如何呢?
<bean id="Car1" class="com.yfyzwr.spring.beans.Car">
<property name="brand" value="红旗"></property>
<property name="price" value="123456.78"></property>
</bean>
<bean id="Car2" class="com.yfyzwr.spring.beans.Car">
<property name="brand" value="红旗"></property>
<property name="price" value="123456.78"></property>
</bean>
<bean id="Person" class="com.yfyzwr.spring.beans.Person" autowire="byType">
<property name="name" value="金三胖"></property>
<property name="age" value="30"></property>
<!-- 这里没有为car属性指定初始值 -->
</bean>
此时运行的结果却是提示NoUniqueBeanDefinitionException错误(Bean的声明不唯一)。
如果容器中有两个(或多个)与所依赖Bean的类型一致的Bean,那么在这种情况下Spring将无法判定哪个Bean最合适该属性, 所以不能执行自动装配。
2. bean的作用域
Spring可以在< bean >元素的 scope 属性里设置 Bean 的作用域。
2-1. singleton
默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一的一个实例, 整个 IOC 容器范围内都能共享该实例:所有后续的 getBean() 调用和 Bean 引用都将返回这个唯一的 Bean 实例。该作用域被称为 singleton, 它是所有 Bean 的默认作用域。
修改Car类的实现。
public class Car private String brand; private double price; public Car() System.out.println("car Constructor……"); public void setBrand(String brand) System.out.println("setBrand"); this.brand = brand; public void setPrice(double price) System.out.println("setPrice"); this.price = price; @Override public String toString() return "Car [brand=" + brand + ", price=" + price + "]";
修改main方法。
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); Car car1 = (Car)context.getBean("Car"); Car car2 = (Car)context.getBean("Car"); System.out.println(car1.hashCode()); System.out.println(car2.hashCode()); context.close();
运行程序,查看结果。
car Constructor……
setBrand
setPrice
363391
363391
对于默认的singleton作用域,在容器加载bean的时候会调用其构造函数和setter函数,对其实例化。之后的所有对bean的使用都是同一实例对象。
2-2. protoType
修改xml文件。
<bean id="Car" class="com.yfyzwr.spring.beans.Car" scope="prototype"> <property name="brand" value="baoma"></property> <property name="price" value="123"></property> </bean>
运行程序,查看结果。
car Constructor……
setBrand
setPrice
car Constructor……
setBrand
setPrice
363391
617995
对于protoType作用域,每次调用getBean()都会得到一个新的实例对象。实例对象不再是容器加载Bean的时候创建,而是调用getBean()的时候才创建。
3. bean的生命周期
Spring IOC 容器对 Bean 的生命周期进行管理的过程:
- 通过构造器或工厂方法创建 Bean 实例。
- 为 Bean 的属性设置值或者是对其他 Bean 的引用。
- 调用 Bean 的初始化方法。
- Bean 可以被使用了。
- 当容器关闭时, 调用 Bean 的销毁方法。
3-1. bean的初始化和销毁
可以在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化方法和销毁方法。
修改Car类的实现,添加init()和destroy()方法。
public void init() //方法名可以任意取名 System.out.println("init..."); public void destroy() //方法名可以任意取名 System.out.println("destroy...");
修改xml文件的实现。
<bean id="Car" class="com.yfyzwr.spring.beans.Car" init-method="init" destroy-method="destroy"> <property name="brand" value="baoma"></property> <property name="price" value="123"></property> </bean>
运行程序,查看结果。
car Constructor……
setBrand
setPrice
init…
Car [brand=baoma, price=123.0]
destroy…
3-2. Bean的后置处理器
Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理。Bean的后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一某个实例。
其典型应用是:检查 Bean 属性的正确性或根据特定的标准更改 Bean 的属性。
对Bean的后置处理器而言, 需要实现org.springframework.beans.factory.config.BeanPostProcessor接口,该接口有两个方法需要被复写,在初始化方法被调用前后, Spring 将把每个 Bean 实例分别传递给这两个方法。
新建MyBeanPostProcessor类并复写方法。
public class MyBeanPostProcessor implements BeanPostProcessor @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException if("Car".equals(beanName)) System.out.println("postProcessBeforeInitialization" + bean + beanName); return bean; @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException if("Car".equals(beanName)) //beanName是指bean的id属性 System.out.println("postProcessAfterInitialization" + bean + beanName); Car car = new Car(); car.setBrand("红旗"); car.setPrice(789); return car; return bean;
为MyBeanPostProcessor添加bean配置,添加如下语句。
<bean class="com.yfyzwr.spring.beans.MyBeanPostProcessor"></bean>
运行程序,查看结果。
car Constructor……
setBrand
setPrice
postProcessBeforeInitializationCar [brand=baoma, price=123.0]Car
init…
postProcessAfterInitializationCar [brand=baoma, price=123.0]Car
car Constructor……
setBrand
setPrice
Car [brand=红旗, price=789.0]
destroy…
从输出结果可以得知,我们通过BeanPostProcessor 接口可以对bean的实例进行自定义的操作。
以上是关于Spring4.0学习笔记004——Bean的配置二(基于XML文件)的主要内容,如果未能解决你的问题,请参考以下文章
Spring4.0学习笔记005——Bean的配置三(基于XML文件)
Spring4.0学习笔记005——Bean的配置三(基于XML文件)
Spring4.0学习笔记003——Bean的配置一(基于XML文件)
Spring4.0学习笔记006——Bean的配置(基于注解)