《Spring2.0 技术手册》读书笔记五-与Spring容器的交互(1)

在前面的例子中,Spring容器在后面管理着Bean实例,我们只需要通过容器门户ApplicationContext或者BeanFactory的getBean()方法来取得实例。但是我们如何使用Spring提供的其他功能呢?如何使用容器中的其他内容呢?即如何与容器交互!

在Bean中获取ApplicationContext/BeanFactory的实例

Bean意识到容器的存在,我们就可以根据自己的需要,取得容器中的资源或使用其他功能,还可以通过容器在某时刻发布事件,让监听此事件的类进行相应处理等。

主要方法是Bean实现Spring中的一些接口:

/** * org.springframework.beans.factory.BeanNameAware接口 * 方法setBeanName()会在该类被容器设置依赖关系后,初始化之前调用, * 参数name即为此Bean在Bean定义文件中的名称 */ public interface BeanNameAware{ void setBeanName(String name); } /** * org.springframework.beans.factory.BeanFactoryAware接口 * 实现此接口的Bean类,在设置依赖关系后、初始化前,容器会调用setBeanFactory()方法, * 将BeanFactory实例注入到Bean中 */ public interface BeanFactoryAware{ void setBeanFactory(BeanFactory beanFactory) throws BeansException; } /** * org.springframework.context.ApplicaiontContextAware接口 * 实现此接口的类,在被初始化后,容器会调用setApplicationContext()方法, * 注入ApplicationContext的实例 * */ public interface ApplicationContextAware { void setApplicationContext(ApplicationContext applicationContext) throws BeansException; } 

当然了,还可以实现其他Aware(意识)接口,取得容器中的相关资源,此处不再介绍。实现了Spring中的相关接口,Bean类就会对容器产生依赖,对该类的重用有一定的影响。

 

Bean事后处理器

通过实现org.springframework.beans.factory.config.BeanPostProcessor接口,在容器对Bean进行初步处理-设置依赖关系后获得控制权,进行相关操作。(postProcessor,事后处理器,这个名字就很恰当的说出了接口的作用)。

BeanPostProcessor接口:

public interface BeanPostProcessor { /** * Bean类被初始化之前调用 * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; if * <code>null</code>, no subsequent BeanPostProcessors will be invoked * @throws BeansException */ Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; /** * Bean类被初始化之后立即执行 * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; if * <code>null</code>, no subsequent BeanPostProcessors will be invoked * @throws BeansException */ Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; } 

通过BeanPostProcessor将所有Bean的字符串属性值改大写,例子如下:

import java.lang.reflect.Field; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; //每个Bean被初始化之后,容器都会调用此类! public class UppercaseModifier implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException { //通过反射来获得Bean类的字段和字段值 Field[] fields= arg0.getClass().getDeclaredFields(); for(int i=0;i<fields.length;i++){ if(fields[i].getType().equals(String.class)){ fields[i].setAccessible(true); String original; try { //获得fields[i]字段在类arg0中的值 original = (String)fields[i].get(arg0); //更改类arg0中字段fields[i]的值 fields[i].set(arg0, original.toUpperCase()); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } return arg0; } @Override public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException { // TODO Auto-generated method stub return arg0; } }  

然后在Bean定义文件中进行配置,让容器知道该类的存在。

<bean id="uppercaseModifier" class="UppercaseModifier"/> 

 

BeanFactory事后处理器

在BeanFactory载入Bean定义文件的所有内容,但没正式产生Bean实例前,通过实现org.springframework.beans.factory.config.BeanFactoryPostProcessor接口,可以对BeanFactory进行一些处理。

注:BeanFactory载入定义文件文件,并不是指在加载定义文件是必须使用BeanFactory factory=new XmlBeanFactory(rs)。使用ApplicationContext读取定义文件也是会激发事件的,因为ApplicationContext本身就是一个BeanFactory。它继承的类有:ListableBeanFactory, HierarchicalBeanFactory,

MessageSource, ApplicationEventPublisher, ResourcePatternResolver。

BeanFactoryPostProcessor:

public interface BeanFactoryPostProcessor { /** * Modify the application context's internal bean factory after its standard * initialization. All bean definitions will have been loaded, but no beans * will have been instantiated yet. This allows for overriding or adding * properties even to eager-initializing beans. * @param beanFactory the bean factory used by the application context * @throws org.springframework.beans.BeansException in case of errors */ void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; } 

如果某个类实现了该接口,要想容器在加载定义文件后调用此类还要在定义文件中配置该类(<bean id="" class=""/>)。Spring提供了几个实现该接口的类,方便我们使用。举例如下:

PropertyPlaceholderConfigurer

org.framework.beans.factory.config.PropertyPlaceholderConfigurer,可以将一些配置信息移出到一个或多个.properties文件中,即这些配置信息可以不用在xml文件中设置了,xml可以专门负责系统的相关设置,实际应用时的需求可以放在.properties文件里面。

直接在定义文件中定义该类,并设置属性location来指出存放有配置信息的.properties文件位置。

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="configBean" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="hello.properties" /> <!-- 还可以使用locations属性,指出多个.properties文件 --> <!-- <property name="locations"> <list> <value>hello.properties</value> <value>other.properties</value> </list> </property> --> </bean> <bean id="helloBean" class="HelloBean"> <!-- spring.placeholder.test的值可以在指定的.properties文件中找到 --> <property name="helloWord" value="${spring.placeholder.test}"></property> </bean> </beans> 

hello.properties文件

spring.placeholder.test=PropertyPlaceholderConfigurer Test 

那么通过getBean("helloBean")获得的HelloBean实例,它的属性helloWord的值将为PropertyPlaceholderConfigurer Test PropertyOverrideConfigurer

org.framework.beans.factory.config.PropertyOverrideConfigurer,通过此类,可以在.properties文件中设置一些优先的属性,不管xml中某个设置与.properties文件中的某个设置是否重复,该设置值都以.properties文件中的设置为主。

bean定义文件

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="configBean" class="org.springframework.beans.factory.config.PropertyOverrideConfigurer"> <property name="location" value="hello.properties"></property> </bean> <bean id="helloBean" class="spring.beanpostprocessor.HelloBean"> <property name="helloWord" value="will be overrided!"></property> </bean> </beans> 

hello.properties

helloBean.helloWord=PropertyOverrideConfigurer 

helloBean实例的属性helloword的值将为PropertyOverrideConfigurer。

CustomEditorConfigurer

org.springframework.beans.factory.config.CustomEditorConfigurer类,可以读取实现java.beans.PropertyEditor接口的类,并按其中的实现,将字符串值转换为指定类型的对象。废话少说,见代码见真理!

public class User { private String name; private int number; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } } import java.beans.PropertyEditorSupport; /** * PropertyEditorSupport类实现了接口PropertyEditor,直接继承该类更为方便 * CustomEditorConfigurer类将读取此类 */ public class UserEditor extends PropertyEditorSupport{ /** * 通过此方法,分析字符串arg0,创建类User实例 */ public void setAsText(String arg0) throws IllegalArgumentException { String[] strs=arg0.split(","); int number=Integer.parseInt(strs[1]); User user=new User(); user.setName(strs[0]); user.setNumber(number); setValue(user); } } public class HelloBean { private String helloWord; private User user; public String getHelloWord() { return helloWord; } public void setHelloWord(String helloWord) { this.helloWord = helloWord; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } 

Bean定义文件配置CustomEditorConfigurer

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="configBean" class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <!-- 设置对应的编辑关系 --> <entry key="spring.customeditor.User"> <bean id="userEditor" class="spring.customeditor.UserEditor"/> </entry> </map> </property> </bean> <bean id="helloBean" class="spring.customeditor.HelloBean"> <property name="helloWord" value="Hello"/> <!-- 属性user为User类型,这时就会使用UserEditor来编辑value产生User实例 --> <property name="user" value="Jack,123456"/> <!-- 以后所有需要User实例的地方,均可以用字符串(以,隔开)代替。 不需要先定义一个User的Bean实例,然后在需要的地方使用ref。 --> </bean> </beans> 

用getBean("helloBean")获得的HelloBean实例user属性为正常的User类实例(name=jack,number=123456)。

转载于:https://www.cnblogs.com/whuqin/archive/2010/11/15/4982113.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值