依赖注入的3种方式
接口注入type1 设置属性注入type2 构造方法注入type3
spring的IOC容器,事实上就是一个实现了BeanFactory接口的可实例化类,
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("application.xml"));
ApplicationContext还提供了国际化支持,时间的发布和通知机制等
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
BeanFactory在getBean时才实例化,ApplicationContext在初始化时就验证所有的XML文件的正确性
支持注解方式注入
<context:component-scan base-package="demo"/>
注释配置和 XML 配置的适用场合
1.注释配置不一定在先天上优于 XML 配置。如果 Bean 的依赖关系是固定的,(如 Service 使用了哪几个 DAO 类),这种配置信息不会在部署时发生调整,那么注释配置优于 XML 配置;反之如果这种依赖关系会在部署时发生调整,XML 配置显然又优于注释配置,因为注释是对 Java 源代码的调整,您需要重新改写源代码并重新编译才可以实施调整。
2.如果 Bean 不是自己编写的类(如 JdbcTemplate、SessionFactoryBean 等),注释配置将无法实施,此时 XML 配置是唯一可用的方式。
3.注释配置往往是类级别的,而 XML 配置则可以表现得更加灵活。比如相比于 @Transaction 事务注释,使用 aop/tx 命名空间的事务配置更加灵活和简单。
所以在实现应用中,我们往往需要同时使用注释配置和 XML 配置,对于类级别且不会发生变动的配置可以优先考虑注释配置;而对于那些第三方类以及容易发生调整的配置则应优先考虑使用 XML 配置。Spring 会在具体实施 Bean 创建和 Bean 注入之前将这两种配置方式的元信息融合在一起。
==============================================================================================================
注入Resource资源
前缀 |
说明 |
示例 |
classpath: |
从classpath加载该资源 |
classpath:config.xml |
http: |
作为URL加载该资源 |
http://java.sun.com |
file: |
作为URL加载该资源 |
file:///C:/windows |
无 |
根据具体的ApplicationContext判断 |
test.txt |
public class ResourceBean {
private UrlResource urlResource;
private ClassPathResource classPathResource;
private FileSystemResource fileSystemResource;
public void setUrlResource(UrlResource urlResource) throws IOException {
this.urlResource = urlResource;
System.out.println(urlResource.getURL());
}
public void setClassPathResource(ClassPathResource classPathResource) throws IOException {
this.classPathResource = classPathResource;
System.out.println(classPathResource.getFile());
}
public void setFileSystemResource(FileSystemResource fileSystemResource) {
this.fileSystemResource = fileSystemResource;
System.out.println(fileSystemResource.getFile());
}
}
<bean id="resourceBean" class="demo.ResourceBean">
<property name="classPathResource" value="classpath:application.xml"/>
<property name="urlResource" value="http://www.iteye.com"/>
<property name="fileSystemResource" value="c:/windows/notepad.exe"/>
</bean>
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:application.xml");
//c:/windows/notepad.exe将被转化为一个ClassPathResource
//ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
ResourceBean resourceBean = (ResourceBean) context.getBean("resourceBean");
==============================================================================================================
Bean的作用域
singleton:开发人员书写的仍是一个普通的Bean,spring并不能阻止应用程序自行的new对象,不应试图在spring容器外部自行创建Bean
prorotye:spring容器一旦将实例new出来交给客户端,就不再对其跟踪引用,所以无法对prototype作用域的Bean定义destroy-method,不过仍可定义init-method
==============================================================================================================
配置工厂Bean
应用程序需要使用自己的工厂对象来创建Bean,如果将这一功能也交给spring容器,spring容器管理的就不是普通的Bean实例,是“工厂”实例,暂且称为“工厂Bean”
context.getBean(xxx);
实际上获得的不是配置文件中 id="xxx" 的bean,而是这个bean的getBean()方法返回的bean
静态工厂:用的极少
实例工程:首先实例化工厂对象,然后才能调用工厂对象的成员方法,这往往因为对象的创建还依赖于工厂实例的内部状态。
public class InstanceFactoryBean {
private String format;
public void setFormat(String format) {
this.format = format;
}
public String createTime(){
return new SimpleDateFormat(format).format(new Date());
}
<bean id="instanceFactoryBean" class="demo.InstanceFactoryBean">
<property name="format" value="yy-MM-dd"/>
</bean>
<bean id="currentTime" factory-bean="instanceFactoryBean" factory-method="createTime"/>
实现FactoryBean接口
public class PIFactoryBean implements FactoryBean{
public Object getObject() throws Exception {
return new Double(3.1415926);
}
public Class getObjectType() {
return Double.class;
}
public boolean isSingleton() {
return true;
}
<bean id="pi" class="demo.PIFactoryBean"/>
context.getBean("pi") //3.1415926
context.getBean("&pi") //PIFactoryBean
常用的FactoryBean
JndiObjectFactoryBean proxyFactoryBean TransactionProxyFactoryBean LocalSessionFactoryBean
==============================================================================================================
自动装配
不用写property @Resource @Autowired
模板装配
<bean abstract="true"....../>
<bean parent=""...../>
==============================================================================================================
定制Bean
获取Bean的信息 |
实现了BeanNameAware接口 |
获取容器 |
实现ApplicationContextAware接口 |
BeanPostProcessor |
Bean初始化的过程会被截获 创建Bean实例->设置Bean属性->Bean自身回调->postProcessBeforeInitialization->调用Bean初始化->调用postProcessAfterInitialization->初始化完成有能力在spring容器对Bean初始化前后对所有Bean进行检查和修改 |
检查依赖注入 |
@Required |
BeanFactoryPostProcessor |
在spring容器对所用的Bean初始化之前,对Bean的定义做一些修改 |
使用外部属性文件 |
PropertyPlaceholderConfiger |
发布和接受事件 |
发布:ApplicationContext的publishEvent()方法。接受:onapplicationEvent()方法 |
容器的继承 |
实现HierarchicalBeanFactory接口 new ClassPathXmlApplicationContext(new String[]{"xxxxx.xml"}, parent) |
定制属性编辑器 |
类名+Editor 继承PropertyEditorSupport 重写setAsText方法 |