通过Java方式
由于Spring的自动装配并不能将第三方库组件装配到应用中,于是需要显式装配配置。显示装配有两种方式
- 通过java代码装配bean
- 通过XML装配bean
Spring In Action作者首推使用自动装配的功能,而后是通过java代码配置bean,最后才用XML文件配置的方式..
那么怎么通过java代码来配置Bean呢??
- 编写一个java类,使用@Configuration修饰该类
- 被@Configuration修饰的类就是配置类
编写配置类:
@org.springframework.context.annotation.Configuration public class Configuration { }
使用配置类创建bean:
- 使用@Bean来修饰方法,该方法返回一个对象。
- 不管方法体内的对象是怎么创建的,Spring可以获取得到对象就行了。
- Spring内部会将该对象加入到Spring容器中
- 容器中bean的ID默认为方法名
@org.springframework.context.annotation.Configuration public class Configuration { @Bean public UserDao userDao() { UserDao userDao = new UserDao(); System.out.println("我是在configuration中的"+userDao); return userDao; } }
- 测试代码:要使用@ContextConfiguration加载配置类的信息【引入test包】
package bb; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; /** * Created by ozc on 2017/5/11. */ //加载配置类的信息 @ContextConfiguration(classes = Configuration.class) public class Test2 { @Test public void test33() { ApplicationContext ac = new ClassPathXmlApplicationContext("bb/bean.xml"); UserDao userDao = (UserDao) ac.getBean("userDao"); System.out.println(userDao); } }
三种方式混合使用
注解和XML配置是可以混合使用的,JavaConfig和XML也是可以混合使用的…
如果JavaConfig的配置类是分散的,我们一般再创建一个更高级的配置类(root),然后使用@Import来将配置类进行组合
如果XML的配置文件是分散的,我们也是创建一个更高级的配置文件(root),然后使用来将配置文件组合
在JavaConfig引用XML
- 使用@ImportResource()
在XML引用JavaConfig
- 使用
<bean>
节点就行了
bean对象创建细节
在Spring第一篇中,我们为什么要引入Spring提出了这么一些问题:
既然我们现在已经初步了解IOC容器了,那么这些问题我们都是可以解决的。并且是十分简单【对象写死问题已经解决了,IOC容器就是控制反转创建对象】
scope属性
指定scope属性,IOC容器就知道创建对象的时候是单例还是多例的了。
属性的值就只有两个:单例/多例
- 当我们使用singleton【单例】的时候,从IOC容器获取的对象都是同一个:
- 当我们使用prototype【多例】的时候,从IOC容器获取的对象都是不同的:
scope属性除了控制对象是单例还是多例的,还控制着对象创建的时间!
- 我们在User的构造函数中打印出一句话,就知道User对象是什么时候创建了。
public User() { System.out.println("我是User,我被创建了"); }
- 当使用singleton的时候,对象在IOC容器之前就已经创建了
- 当使用prototype的时候,对象在使用的时候才创建
lazy-init属性
lazy-init属性只对singleton【单例】的对象有效…..lazy-init默认为false….
有的时候,可能我们想要对象在使用的时候才创建,那么将lazy-init设置为ture就行了
init-method和destroy-method
如果我们想要对象在创建后,执行某个方法,我们指定为init-method属性就行了。。
如果我们想要IOC容器销毁后,执行某个方法,我们指定destroy-method属性就行了。
<bean id="user" class="User" scope="singleton" lazy-init="true" init-method="" destroy-method=""/>
Bean创建细节总结
/** * 1) 对象创建: 单例/多例 * scope="singleton", 默认值, 即 默认是单例 【service/dao/工具类】 * scope="prototype", 多例; 【Action对象】 * * 2) 什么时候创建? * scope="prototype" 在用到对象的时候,才创建对象。 * scope="singleton" 在启动(容器初始化之前), 就已经创建了bean,且整个应用只有一个。 * 3)是否延迟创建 * lazy-init="false" 默认为false, 不延迟创建,即在启动时候就创建对象 * lazy-init="true" 延迟初始化, 在用到对象的时候才创建对象 * (只对单例有效) * 4) 创建对象之后,初始化/销毁 * init-method="init_user" 【对应对象的init_user方法,在对象创建之后执行 】 * destroy-method="destroy_user" 【在调用容器对象的destroy方法时候执行,(容器用实现类)】 */