一、BeanFactory轻量级
三种访问ApplicationContext.xml方式:
1、Resource resource = new ClassPathResource(“application.xml”);
BeanFactory factory = new XmlBeanFactory(resource);
HelloWorld hello = factory.getBean(“fileHelloWorld”);
2、基于文件找到application.xml
InputStream is = new FileInputStream(“src/application.xml”);
BeanFactory factory = new XmlBeanFactory(is);
3、基于ApplicationContext
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[]{“application.xml”});
BeanFactory factory = (BeanFactory)appContext;
Bean的生命周期
1、实例化JavaBean
2、JavaBean实例初始化,即通过IOC注入其依赖性。这一阶段将完成JavaBean实例初始化
3、基于Spring应用对JavaBean实例的使用
4、IOC容器销毁JavaBean实例
Bean的创建
<bean name="fileHelloWorld" class="com.jader.FileHelloWorld">
HelloWorld实例将使用无参数构建器创建出来
<bean name="fileHelloWorld" class="com.jader.FileHelloWorld" factory-method="createHelloWorldInstance">
HelloWorld必须提供createHelloWorldInstance的静态方法
<bean name="helloWorldFactory" class="com.jader.FileHelloWorldFactory" />
<bean name="fileHelloWorld" class="com.jader.FileHelloWorld" factory-bean="helloWorldFactory' factory-method="createFileHelloWorldInstance">
此种情况类不需要提供静态方法,命名为fileHelloWorld的JavaBean实例将通过helloWorldFactory工厂类的createFileHelloWorldInstance方法获得
<bean name="fileHelloWorld" class="com.jader.FileHelloWorld">
<constructor-arg>
<ref bean="fileHello"/>
</constructor>
</bean>
通过ref元素引用Spring配置文件中的fileHello,ref有以下几个属性:
1、bean:在当前Spring XML配置文件中,或者在同一个BeanFactory(applicationContext)中的其他JavaBean中
2、local:在当前Spring XML配置文件中,其依赖的JavaBean必须存在于当前Spring XML配置文件中,
3、parent:用于指定其依赖的父JavaBean定义
初始化JavaBean
1、如果开发者使用了元素的autowire属性,Spring能够自动将目标JavaBean需要注入的JavaBean找到并注入进来。
2、如果开发者指定了元素的dependency-check属性,则能够保证各个Spring配置文件中各个JavaBean之间的相互关系。
3、借助于setter方法能够将JavaBean的属性值注入进来,这些属性可以是Java原型(primitive)、对象类型,甚至可以是null
例如:
<bean id="helloWorld" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="transactionManager"/>
</property>
<property name="transactionAttributers">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="set*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
Spring框架能够注入TransactionProxyFactoryBean中的transactionManager、target、transactionAttributes所需的属性值。比如:transactionManager属性取值通过ref引用了transactionManager的POJO服务。如果Spring配置文件中不存在事务管理器,开发者有两种做法:
单独定义新的transactionManager,例如:
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransactionName">
<value>java:comp/UserTransaction</value>
</property>
</bean>
ref会引用transactionManager
定义内部JavaBean方法:
<propery name="transactionManager">
<bean class="org.springframework.transaction.jat.JtaTransactionManager">
<property name="userTransactionName">
<value>java:comp/UserTransaction</value>
</property>
</bean>
</property>
通过定义内部JavaBean,其他JavaBean便不能够引用到他,而且开发者再也不能够重用JtaTransactionManager。现实场合存在这种需求,存在即是合理。
4、如果JavaBean实现了如下接口,还需要调用setBeanFactory方法
org.springframework.beans.factory.BeanFactoryAware
其定义了方法如下:
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
5、Spring框架提供了若干接口,供开发者改变配置再BeanFactory中JavaBean的行为适用,其中InitializingBean接口介绍如下:
org.springframework.beans.factory.InitializingBean在BeanFactory初始化JavaBean时,BeanFactory会调用那些实现了InitializingBean接口的JavaBean中包含的方法:
void afterPropertiesSet() throws Exception;// InitializingBean定义的方法
6、最后通过在元素中包含init-method属性能够达到同InitializingBean一样的目的,即:
<bean name="fileHelloWorld" class="com.openv.spring.HelloWorld" init-method="init">
HelloWorld将实现init方法
通过以上6步,完成JavaBean实例的初始化工作
使用JavaBean
借助于getBean方法,开发者就能够在应用中使用他了
销毁JavaBean
一旦将基于Spring的应用停止,Spring框架将调用那些JavaBean实例中存在的生命周期方法,比如:DisposableBean接口的JavaBean或者那些在Spring配置文件中指定了destory-method属性的JavaBean。
最终Spring将销毁JavaBean实例。
注意:这些内容只适合于那些通过singleton方法创建的JavaBean实例,对于那些以prototype方式创建的JavaBean实例,Spring并不能够控制器生命周期,因为这种JavaBean实例创建成功,整个JavaBean将交付给Spring应用去管理。
其中,DisposableBean介绍如下:
org.springframework.beans.factory.DisposableBean:在BeanFactory销毁JavaBean时,BeanFactory会调用那些实现了DisposableBean接口的JavaBean中包含的如下方法:
void destory() throws Exception;
其中,destroy是DisposableBean定义的方法。
当然,通过在元素中包含destroy-method属性能够达到同DisposableBean一样的目的,即:
<bean name="fileHelloWorld" class="com.openv.spring.HelloWorld" destroy-method="destroy"></bean>
如果应用同事实现了两种方法,Spring先执行DisposableBean中的的destroy方法。
抽象Bean和子Bean定义
将公共内容放置在抽象bean中,子Bean能够重用抽象Bean中定义的内容,而且还能够“重载”他们。
PropertyPlaceholderConfigurer和PropertyOverrideConfigurer
对于PropertyPlaceholderConfigurer而言,他能够在Spring配置文件外部配置其他应用使用到的属性,比如:通过Java属性文件配置数据库连接信息、LDAP(目录访问协议)、活动目录连接信息。
例如:Apache DBCP数据源实例:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"
<value>${jdbc.driverClassName}</value>
</property>
<property name="url">
<value>${jdbc.url}</value>
</property>
<property name="username">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
</bean>
其中$里面的驱动名、url、用户名、密码的实际值通过Java属性文件获得。
<bean id="propertyConfigurer" class="org.springframework.bean.factory.config.ProperryPlaceholderConfigurer">
<property name="location">
<value>jdbc.properties</value>
</property>
</bean>
BeactoryAware与BeanNameAware
对于某些基于Spring的应用而言,有一些将应用的BeanFactory实例注入到JavaBean实例中。比如:为在某JavaBean实例中动态获得BeanFactory创建的某单例JavaBean,但是该单例JavaBean并没有显式的使用它,此时借助于BeanFactoryAware能够满足开发者要求,例如:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:/MysqlDS</value>
</property>
</bean>
<bean id="exampleServiceTarget" class="com.openv.spring.service.impl.ExampleManagerImpl">
<property name="userInfo">
<ref local="userInfoDao" />
</property>
</bean>
如果在exampleServiceTarget中需要使用dataSource,但是在Spring配置文件中并没有显式的配置对dataSource的引用。此时,需要借助于BeanFactoryAware,即ExampleManagerImpl需要实现BeanFactoryAware接口。
如果需要在JavaBean实例中获悉其配置的名字,可以考虑实现BeanNameAware接口:
org.springframework.beans.factory.BeanNameAware
其定义了如下方法:
void setBeanName(String name);
其执行时间在调用InitializingBean afterPropertiesSet或者自定义init-method之前,而在JavaBean属性正常赋值之后。
二、ApplicationContext
Spring框架引入了ApplicationContext接口,开发者不需要手工创建ApplicationContext实例,便可以声明的方式使用它。例如:
org.springframework.web.context.ContextLoaderServlet或者
org.springframework.web.context.ContextLoaderListener
能够在web应用启动的时候自动实例化ApplicationContext对象,对于SpringBeanFactory而言,如果用户没有调用getBean()方法,则使用到的JavaBean实例将会被创建。因此在BeanFactory中使用了延迟装载的机制,这主要是同BeanFactory的应用场合有关。对于Spring ApplicationContext而言,一旦ContextLoaderServlet或ContextLoaderListener初始化成功所有的JavaBean实例将会被创建(除非开发者改变了ApplicationContext的默认行为,比如显式的设置延迟装载行为)
开发者应该注意到Log4jConfigServlet,供配置Spring应用的日志使用,使用方法同ContextLoaderServlet,如下:
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<servlet>
<serlvet-name>log4jConfigServlet</servlet-name>
<serlvet-class>
org.springframework.web.util.Log4jConfigServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
(>0表示容器在应用启动时就加载并初始化这个servlet,
当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载,
正数的值越小,该servlet的优先级越高,应用启动时就越先加载)
开发者应该注意到Log4jConfigListener类供配置Spring应用的日志使用,由于ApplicationContext含有BeanFactory的所有功能,因此对于开发J2EE应用场合推荐使用ApplicationContext。
1、Web应用中创建ApplicationContext
Web应用自动过程中将自动初始化监听器,而ContextLoaderListener就是监听器,例如:
<context-param>
<param-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
2、ApplicationContextAware
在为某JavaBean实例动态获得ApplicationContext创建的某单例JavaBean,但是该单例JavaBean并没有显式的使用(在Spring配置文件没有显式的给出对单例JavaBean的引用,例如未使用元素),借助于ApplicationContextAware能够满足开发者的要求
介绍如下:
org.springframework.context.ApplicationContextAware
其定义了如下方法:
void setApplicationContext(ApplicationContext applicationContext);
现有如下示例代码:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" >
<property name="jndiName">
<value> java:/MySqlDS</value>
</property>
</bean>
<bean id="exampleServiceTarget" class="com.openv.spring.service.impl.ExampleManagerImpl">
<property name="userInfo">
<ref local="userInfoDao" />
</property>
</bean>
如果在exampleServiceTarget需要使用到dataSource,但是Spring配置文件中没有显式的配置对dataSource的引用,此时可以借助ApplicationContextAware接口。
示例代码:
public class ExampleManagerImpl implements ApplicationContextAware{
private ApplciationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext){
this.applicationContext = applicationContext;
}
pubic DataSource getDataSource(){
DataSource ds = null;
ds = (DataSource)applicationContext.getBean("dataSource");
retrun ds;
}
}
这同BeanFactoryAware类似。
3、ApplicationContext接口实现
ClassPathXmlApplicationContext:在Web应用中,开发者可以从其classpath中,即WEB-INF/classes或WEB-INF/lib的jar中装载Spring配置文件
FileSystemXMLApplicationContext:开发者可以从文件系统中装载Spring配置文件
XMLWebApplicationContext:供ContextLoaderListener或ContextLoaderServlet内部装载Spring配置文件使用。