Spring高级程序设计 4 spring 进阶(介绍了大量的Spring特性和对控制反转的补充)(笔记)

来源:互联网 发布:js快速排序算法 编辑:程序博客网 时间:2024/06/06 00:19
1Spring对应用程序可移植性的影响 

不要凭空杜撰对可移植性的需求。在许多情况下,终端用户并不关心你的应用程序是否能在3个不同的控制反转容器上运行,而只要求他能稳定运行。 


2管理bean的生命周期 

两个生命周期时间与bean关系尤为重要: 
postinitialization(初始化后)和predestruction(销毁前)。
 

(Spring并不管理那些被配置成非单例bean的生命周期) 



指定初始化方法: 
view plaincopy to clipboardprint?
  1. package cn.partner4java.init;  
  2.   
  3. /** 
  4. * 指定初始化方法 
  5. * @author partner4java 
  6. * 
  7. */  
  8. public class SimpleBean {  
  9.     private String name;  
  10.     private int age = 0;  
  11.       
  12.     public void init(){  
  13.         if(name == null){  
  14.             System.out.println("name为空");  
  15.         }  
  16.         if(age == 0){  
  17.             System.out.println("age为0");  
  18.         }  
  19.     }  
  20.       
  21.     public String getName() {  
  22.         return name;  
  23.     }  
  24.     public void setName(String name) {  
  25.         this.name = name;  
  26.     }  
  27.     public int getAge() {  
  28.         return age;  
  29.     }  
  30.     public void setAge(int age) {  
  31.         this.age = age;  
  32.     }  
  33.       
  34. }  
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.                   
  8.     <bean id="simple1" class="cn.partner4java.init.SimpleBean"  
  9.             init-method="init">  
  10.         <property name="age" value="29"/>  
  11.         <property name="name" value="Dr. Jekyll"/>  
  12.     </bean>  
  13.     <bean id="simple2" class="cn.partner4java.init.SimpleBean"  
  14.             init-method="init">  
  15.         <property name="age" value="29"/>  
  16.     </bean>  
  17.     <bean id="simple3" class="cn.partner4java.init.SimpleBean"  
  18.             init-method="init">  
  19.         <property name="name" value="Mr. Hyde"/>  
  20.     </bean>  
  21.   
  22. </beans>  

调用:
view plaincopy to clipboardprint?
  1.         //在调用获取的时候就会调用init,在调用init之前,已经使用控制反转设置方法依赖注入设置进数据  
  2.         BeanFactory beanFactory = getBeanFactory();  
  3.         System.out.println("simple1");  
  4.         beanFactory.getBean("simple1");  
  5.         System.out.println("simple2");  
  6.         beanFactory.getBean("simple2");  
  7.         System.out.println("simple3");  
  8.         beanFactory.getBean("simple3");  
  9.           
  10. //      后台打印:  
  11. //      simple1  
  12. //      simple2  
  13. //      name为空  
  14. //      simple3  
  15. //      age为0  




实现InitializingBean接口: 
Spring中InitializingBean接口允许你在bean的代码中这样定义:你希望bean能接收到Spring已经完成对其配置的通知。就像使用初始化方法时一样,你可以借机检查bean的配置以确保其有效,若要必要,还可以给出默认值。
view plaincopy to clipboardprint?
  1. public class SimpleBeanIB implements InitializingBean {  
  2.     private static final String DEFAULT_NAME = "Jan Machacek";  
  3.     private String name;  
  4.     private int age = 0;  
  5.   
  6.     public String getName() {  
  7.         return name;  
  8.     }  
  9.   
  10.     public void setName(String name) {  
  11.         this.name = name;  
  12.     }  
  13.   
  14.     public int getAge() {  
  15.         return age;  
  16.     }  
  17.   
  18.     public void setAge(int age) {  
  19.         this.age = age;  
  20.     }  
  21.   
  22.     @Override  
  23.     public String toString() {  
  24.         final StringBuilder sb = new StringBuilder();  
  25.         sb.append("SimpleBean");  
  26.         sb.append("{name='").append(name).append('\'');  
  27.         sb.append(", age=").append(age);  
  28.         sb.append('}');  
  29.         return sb.toString();  
  30.     }  
  31.   
  32.     public void afterPropertiesSet() throws Exception {  
  33.         System.out.println("initializing bean");  
  34.         if (this.name == null) {  
  35.             System.out.println("No name specified, using default.");  
  36.             this.name = DEFAULT_NAME;  
  37.         }  
  38.         if (this.age == 0) {  
  39.             throw new IllegalArgumentException("You must set the [age] property bean of type [" + getClass().getName() + "]");  
  40.         }  
  41.     }  
  42. }  


决议顺序: 
Spring首先调用InitializingBean.afterPropertiesSet()方法,然后再调用初始化方法。(建议如果存在顺序,都写入到afterPropertiesSet中调用。) 


afterPropertiesSet方法和类的继承: 
例子抽象父类实现了接口,但是把afterPropertiesSet定义成了final,不可被子类覆盖,也就是去实现一些通用的初始化,然后再调用了自己定义的initSimple()初始化方法。 
父类:
view plaincopy to clipboardprint?
  1. public abstract class SimpleBeanSupport implements InitializingBean {  
  2.     private String value;  
  3.   
  4.     /** 
  5.      * Subclasses may override this method to perform additional initialization. 
  6.      * This method gets invoked after the initialization of the {@link SimpleBeanSupport} 
  7.      * completes. 
  8.      * @throws Exception If the subclass initialization fails. 
  9.      */  
  10.     protected void initSimple() throws Exception {  
  11.         // do nothing  
  12.     }  
  13.   
  14.     public final void afterPropertiesSet() throws Exception {  
  15.         Assert.notNull(this.value, "The [value] property of [" + getClass().getName() + "] must be set.");  
  16.         initSimple();  
  17.     }  
  18.   
  19.     public final void setValue(String value) {  
  20.         this.value = value;  
  21.     }  
  22.   
  23.     protected final String getValue() {  
  24.         return this.value;  
  25.     }  
  26. }  

继承:
view plaincopy to clipboardprint?
  1. public class SoutSimpleBean extends SimpleBeanSupport {  
  2.     private String person;  
  3.   
  4.     protected void initSimple() throws Exception {  
  5.         Assert.notNull(this.person, "The [person] property of [" + getClass().getName() + "] must be set.");  
  6.     }  
  7.   
  8.     public void setPerson(String person) {  
  9.         this.person = person;  
  10.     }  
  11.   
  12.     @Override  
  13.     public String toString() {  
  14.         return String.format("%s says \"%s\""this.person, getValue());  
  15.     }  
  16. }  

配置文件:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.   
  8.     <bean id="simple1" class="com.apress.prospring2.ch04.lifecycle.SoutSimpleBean">  
  9.         <property name="person" value="Winston Churchill"/>  
  10.         <property name="value" value="This report, by its very length, defends itself against the risk of being read."/>  
  11.     </bean>  
  12.   
  13. </beans>  



嵌入bean的销毁: 
1、bean销毁时执行某一方法
view plaincopy to clipboardprint?
  1. public class DestructiveBean implements InitializingBean {  
  2.     private InputStream is = null;  
  3.     private String filePath = null;  
  4.   
  5.     public void afterPropertiesSet() throws Exception {  
  6.         System.out.println("Initializing Bean");  
  7.   
  8.         Assert.notNull(this.filePath, "The [filePath] property of [" + getClass().getName() + "] must be set.");  
  9.   
  10.         new File(this.filePath).createNewFile();  
  11.         this.is = new FileInputStream(this.filePath);  
  12.     }  
  13.   
  14.     public void destroy() {  
  15.         System.out.println("Destroying Bean");  
  16.   
  17.         if (this.is != null) {  
  18.             try {  
  19.                 this.is.close();  
  20.                 this.is = null;  
  21.                 new File(this.filePath).delete();  
  22.             } catch (IOException ex) {  
  23.                 System.err.println("WARN: An IOException occured"  
  24.                         + " while trying to close the InputStream");  
  25.             }  
  26.         }  
  27.     }  
  28.   
  29.     public void setFilePath(String filePath) {  
  30.         this.filePath = filePath;  
  31.     }  
  32.   
  33.     @Override  
  34.     public String toString() {  
  35.         final StringBuilder sb = new StringBuilder();  
  36.         sb.append("DestructiveBean");  
  37.         sb.append("{is=").append(is);  
  38.         sb.append(", filePath='").append(filePath).append('\'');  
  39.         sb.append('}');  
  40.         return sb.toString();  
  41.     }  
  42. }  

配置文件:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.   
  8.     <bean id="destructive" class="com.apress.prospring2.ch04.lifecycle.DestructiveBean"  
  9.             destroy-method="destroy">  
  10.         <property name="filePath" value="/tmp/prospring25"/>  
  11.     </bean>  
  12.   
  13. </beans>  

2、实现DisposableBean接口 
DisposableBean接口提供了destory方法。
view plaincopy to clipboardprint?
  1. public class DestructiveBeanI implements InitializingBean, DisposableBean {  
  2.     private InputStream is = null;  
  3.     private String filePath = null;  
  4.   
  5.     public void afterPropertiesSet() throws Exception {  
  6.         System.out.println("Initializing Bean");  
  7.   
  8.         Assert.notNull(this.filePath, "The [filePath] property of [" + getClass().getName() + "] must be set.");  
  9.   
  10.         new File(this.filePath).createNewFile();  
  11.         this.is = new FileInputStream(this.filePath);  
  12.     }  
  13.   
  14.     public void destroy() {  
  15.         System.out.println("Destroying Bean");  
  16.   
  17.         if (this.is != null) {  
  18.             try {  
  19.                 this.is.close();  
  20.                 this.is = null;  
  21.                 new File(this.filePath).delete();  
  22.             } catch (IOException ex) {  
  23.                 System.err.println("WARN: An IOException occured"  
  24.                         + " while trying to close the InputStream");  
  25.             }  
  26.         }  
  27.     }  
  28.   
  29.     public void setFilePath(String filePath) {  
  30.         this.filePath = filePath;  
  31.     }  
  32.   
  33.     @Override  
  34.     public String toString() {  
  35.         final StringBuilder sb = new StringBuilder();  
  36.         sb.append("DestructiveBean");  
  37.         sb.append("{is=").append(is);  
  38.         sb.append(", filePath='").append(filePath).append('\'');  
  39.         sb.append('}');  
  40.         return sb.toString();  
  41.     }  
  42. }  

配置文件:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.   
  8.     <bean id="destructive" class="com.apress.prospring2.ch04.lifecycle.DestructiveBeanI">  
  9.         <property name="filePath" value="/tmp/prospring25"/>  
  10.     </bean>  
  11.   
  12. </beans>  

3、使用关闭钩子
 
注入关闭代码:
view plaincopy to clipboardprint?
  1. public class ShutdownHook implements Runnable {  
  2.     private ConfigurableListableBeanFactory beanFactory;  
  3.   
  4.     public ShutdownHook(ConfigurableListableBeanFactory beanFactory) {  
  5.         Assert.notNull(beanFactory, "The 'beanFactory' argument must not be null.");  
  6.         this.beanFactory = beanFactory;  
  7.     }  
  8.   
  9.     public void run() {  
  10.         this.beanFactory.destroySingletons();  
  11.     }  
  12. }  

调用代码:
view plaincopy to clipboardprint?
  1. public class ShutdownHookDemo {  
  2.   
  3.     public static void main(String[] args) throws IOException {  
  4.         XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("/META-INF/spring/lifecycledemo5-context.xml"));  
  5.         Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook(factory)));  
  6.         new BufferedInputStream(System.in).read();  
  7.     }  
  8.   
  9. }  





4使用方法注入 

查找方法注入: 
单例比非单例快上百倍、手工使用beanFactory查找bean要比依靠spring获取实体bean快一倍 


方法替换: 






5使用FactoryBean接口 

当你无法使用new操作符来新建类对象,但又想将他们作为Spring的bean来使用时,FactoryBean是一个完美的解决方案。 

FactoryBean接口声明了3个方法:getObject、getObjectType和isSingleton。 
getObject:方法获取由FactoryBean创建的对象。这是一个真正被传给其他使用FactoryBean作为协作者的bean的对象。 
getObjectType: 告诉Spring你的FactoryBean将返回什么类型的对象。如果事先不知道返回什么类型,将返回null。 
isSingleton:告诉Spring,正在被Spring管理的是否为单例实例。
 

例子:
view plaincopy to clipboardprint?
  1. public class MessageDigestFactoryBean implements FactoryBean, InitializingBean {  
  2.     private static final String DEFAULT_ALGORITHM = "MD5";  
  3.       
  4.     private String algorithm = DEFAULT_ALGORITHM;  
  5.     private MessageDigest messageDigest;  
  6.       
  7.     public Object getObject() throws Exception {  
  8.         return this.messageDigest.clone();  
  9.     }  
  10.   
  11.     public Class getObjectType() {  
  12.         return MessageDigest.class;  
  13.     }  
  14.   
  15.     public boolean isSingleton() {  
  16.         return true;  
  17.     }  
  18.   
  19.     public void setAlgorithm(String algorithm) {  
  20.         this.algorithm = algorithm;  
  21.     }  
  22.   
  23.     public void afterPropertiesSet() throws Exception {  
  24.         this.messageDigest = MessageDigest.getInstance(this.algorithm);  
  25.     }  
  26. }  

配置:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.   
  8.     <bean id="sha" class="com.apress.prospring2.ch04.factoy.MessageDigestFactoryBean">  
  9.         <property name="algorithm" value="SHA1"/>  
  10.     </bean>  
  11.   
  12.     <bean id="md5" class="com.apress.prospring2.ch04.factoy.MessageDigestFactoryBean"/>  
  13.       
  14. </beans>  

调用:
view plaincopy to clipboardprint?
  1. public class MessageDigestDemo {  
  2.   
  3.     public static void main(String[] args) {  
  4.         XmlBeanFactory factory = new XmlBeanFactory(  
  5.                 new ClassPathResource("/META-INF/spring/factorydemo-context.xml")  
  6.         );  
  7.         MessageDigest d1 = (MessageDigest)factory.getBean("sha");  
  8.         MessageDigest d2 = (MessageDigest)factory.getBean("md5");  
  9.         calculateDigest("Hello, world", d1);  
  10.         calculateDigest("Hello, world", d2);  
  11.     }  
  12.   
  13.     private static void calculateDigest(String message, MessageDigest digest) {  
  14.         System.out.print("Digest using " + digest.getAlgorithm() + ": ");  
  15.         digest.reset();  
  16.         final byte[] bytes = digest.digest(message.getBytes());  
  17.         for (byte b : bytes) {  
  18.             System.out.print(String.format("%02x", b));  
  19.         }  
  20.         System.out.println("");  
  21.     }  
  22.   
  23. }  


直接访问FactoryBean: 
在调用getBean时在bean名字前面添加一个“&”作为前缀就可以获取FactoryBean。 
view plaincopy to clipboardprint?
  1. XmlBeanFactory factory = new XmlBeanFactory(  
  2.         new ClassPathResource("/META-INF/spring/factorydemo-context.xml")  
  3. );  
  4. MessageDigestFactoryBean factoryBean = (MessageDigestFactoryBean)factory.getBean("&sha");  
  5. MessageDigest d1 = (MessageDigest)factory.getBean("sha");  
  6. MessageDigest d2 = (MessageDigest)factoryBean.getObject();  
  7. System.out.println("Equal MessageDigests created? "  
  8.         + (d1.getAlgorithm().equals(d2.getAlgorithm())));  







6BeanFactoryPostProcessor类 
Spring BeanFactoryPostProcessor类 (“排队”“后”控制修改beanfactory管理的bean) 

他可以获取beanfactory可以加载到的配置信息,然后可以修改这些信息,导致创建的bean得到了你期望的修改。 


BeanFactoryPostProcessor的概念跟BeanPostProcessor相似:BeanFactoryPostProcessor会在Spring构建完BeanFactory之后,BeanFactory构建其他bean之前执行。 
(提示:实际上,Spring可以检测到BeanFactoryPostProcessor bean并在BeanFactory初始化其他任何bean之前初始化他们) 


Spring中BeanFactory的回调处理器: 
AspectJWeavingEnabler:此回调处理器注册AspectJ的ClassPreProcessorAgentAdapter类并在Spring的LoadTimeWeaver中使用。 
Post-processor that registers AspectJ's org.aspectj.weaver.loadtime.ClassPreProcessorAgentAdapter with the Spring application context's default org.springframework.instrument.classloading.LoadTimeWeaver. 

CustomAutowireConfigurer:此类可以让你指定注解,除了@Qualifier之外,标识一个bean是自动织入的志愿者。 
A org.springframework.beans.factory.config.BeanFactoryPostProcessor implementation that allows for convenient registration of custom autowire qualifier types. 
<bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"> 
<property name="customQualifierTypes"> 
<set> 
<value>mypackage.MyQualifier</value> 
</set> 
</property> 
</bean> 

CustomEditorConfigurer:此类注册一个PropertyEditor实现,该实现用户将配置文件中的字符串值转换为bean需要的类型。 
BeanFactoryPostProcessor implementation that allows for convenient registration of custom property editors. 
As of Spring 2.0, the recommended usage is to use custom PropertyEditorRegistrar implementations that in turn register any desired editors on a given registry. Each PropertyEditorRegistrar can register any number of custom editors. 
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"> 
<property name="propertyEditorRegistrars"> 
<list> 
<bean class="mypackage.MyCustomDateEditorRegistrar"/> 
<bean class="mypackage.MyObjectEditorRegistrar"/> 
</list> 
</property> 
</bean> 
Alternative configuration example with custom editor classes: 
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"> 
<property name="customEditors"> 
<map> 
<entry key="java.util.Date" value="mypackage.MyCustomDateEditor"/> 
<entry key="mypackage.MyObject" value="mypackage.MyObjectEditor"/> 
</map> 
</property> 
</bean> 
Also supports "java.lang.String[]"-style array class names and primitive class names (e.g. "boolean"). Delegates to ClassUtils for actual class name resolution. 

CustomScopeConfigurer:使用回调处理器在配置文件中配置自定义作用域(除了单例、原型、请求、会话和全局会话之外)。赋值作用域属性到一个Map类型,他包含作用域名的键,并使用作用域接口的实现作为值。 
Simple BeanFactoryPostProcessor implementation that registers custom Scope(s) with the containing ConfigurableBeanFactory. 
Will register all of the supplied scopes with the ConfigurableListableBeanFactory that is passed to the postProcessBeanFactory(ConfigurableListableBeanFactory) method. 
This class allows for declarative registration of custom scopes. Alternatively, consider implementing a custom BeanFactoryPostProcessor that calls ConfigurableBeanFactory.registerScope programmatically. 

PreferencesPlaceholderConfigurer:此回调处理器将JDK1.4Preperences API替换bean属性中的值,此Preperences API标识他将解析来自用户Preperences的值,然后系统Preperences获得值,最后从一个引用文件获得值。 
Subclass of PropertyPlaceholderConfigurer that supports JDK 1.4's Preferences API (java.util.prefs). 
Tries to resolve placeholders as keys first in the user preferences, then in the system preferences, then in this configurer's properties. Thus, behaves like PropertyPlaceholderConfigurer if no corresponding preferences defined. 
Supports custom paths for the system and user preferences trees. Also supports custom paths specified in placeholders ("myPath/myPlaceholderKey"). Uses the respective root node if not specified. 

PropertyOverrideConfigurer:此回调处理器将替换bean属性值,而值是从指定属性文件装载的。他将从属性文件搜索使用bean名和参数构造的属性。对于bean x,他将在属性文件中查找x.a。若属性并不存在,回调处理器将不会理睬从配置文件中发现的值。 
Property resource configurer that overrides bean property values in an application context definition. It pushes values from a properties file into bean definitions. 
Configuration lines are expected to be of the following form: 
beanName.property=value 
Example properties file: 
dataSource.driverClassName=com.mysql.jdbc.Driver 
dataSource.url=jdbc:mysql:mydb 
In contrast to PropertyPlaceholderConfigurer, the original definition can have default values or no values at all for such bean properties. If an overriding properties file does not have an entry for a certain bean property, the default context definition is used. 
Note that the context definition is not aware of being overridden; so this is not immediately obvious when looking at the XML definition file. 
In case of multiple PropertyOverrideConfigurers that define different values for the same bean property, the last one will win (due to the overriding mechanism). 
Property values can be converted after reading them in, through overriding the convertPropertyValue method. For example, encrypted values can be detected and decrypted accordingly before processing them. 

PropertyPlaceholderConfigurer:此回调处理器将替换从已配置的属性文件装载的属性值。只要值符合某种格式规则,就会发生替换。 
A property resource configurer that resolves placeholders in bean property values of context definitions. It pulls values from a properties file into bean definitions. 
The default placeholder syntax follows the Ant / Log4J / JSP EL style: 
${...} 
Example XML context definition: 
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
<property name="driverClassName"><value>${driver}</value></property> 
<property name="url"><value>jdbc:${dbname}</value></property> 
</bean> 
Example properties file: 
driver=com.mysql.jdbc.Driver 
dbname=mysql:mydb 
PropertyPlaceholderConfigurer checks simple property values, lists, maps, props, and bean names in bean references. Furthermore, placeholder values can also cross-reference other placeholders, like: 
rootPath=myrootdir 
subPath=${rootPath}/subdir 
In contrast to PropertyOverrideConfigurer, this configurer allows to fill in explicit placeholders in context definitions. Therefore, the original definition cannot specify any default values for such bean properties, and the placeholder properties file is supposed to contain an entry for each defined placeholder. 
If a configurer cannot resolve a placeholder, a BeanDefinitionStoreException will be thrown. If you want to check against multiple properties files, specify multiple resources via the "locations" setting. You can also define multiple PropertyPlaceholderConfigurers, each with its own placeholder syntax. 
Default property values can be defined via "properties", to make overriding definitions in properties files optional. A configurer will also check against system properties (e.g. "user.dir") if it cannot resolve a placeholder with any of the specified properties. This can be customized via "systemPropertiesMode". 
Note that the context definition is aware of being incomplete; this is immediately obvious to users when looking at the XML definition file. Hence, placeholders have to be resolved; any desired defaults have to be defined as placeholder values as well (for example in a default properties file). 
Property values can be converted after reading them in, through overriding the convertPropertyValue method. For example, encrypted values can be detected and decrypted accordingly before processing them. 

ServletContextPropertyPlaceholderConfigurer:此回调处理器泛化了PropertyPlaceholderConfigurer类。因此,只要bean属性遵照指定命名规范,他就替换bean的属性。除了他的超类,此处理器还将从处理应用程序的servlet上下文参数入口装载值。 
Subclass of PropertyPlaceholderConfigurer that resolves placeholders as ServletContext init parameters (that is, web.xml context-param entries). 
Can be combined with "locations" and/or "properties" values in addition to web.xml context-params. Alternatively, can be defined without local properties, to resolve all placeholders as web.xml context-params (or JVM system properties). 
If a placeholder could not be resolved against the provided local properties within the application, this configurer will fall back to ServletContext parameters. Can also be configured to let ServletContext init parameters override local properties (contextOverride=true). 
Optionally supports searching for ServletContext attributes: If turned on, an otherwise unresolvable placeholder will matched against the corresponding ServletContext attribute, using its stringified value if found. This can be used to feed dynamic values into Spring's placeholder resolution. 
If not running within a WebApplicationContext (or any other context that is able to satisfy the ServletContextAware callback), this class will behave like the default PropertyPlaceholderConfigurer. This allows for keeping ServletContextPropertyPlaceholderConfigurer definitions in test suites. 




例子:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.   
  8.     <bean id="bfpp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  9.         <property name="location" value="classpath:/META-INF/bfpp.properties"/>  
  10.     </bean>  
  11.   
  12.     <bean id="simpleBean" class="com.apress.prospring2.ch04.bfpp.SimpleBean">  
  13.         <property name="connectionString" value="${simpleBean.connectionString}"/>  
  14.         <property name="password" value="${simpleBean.password}"/>  
  15.         <property name="username" value="username"/>  
  16.     </bean>  
  17.   
  18. </beans>  

调用获取BeanFactoryPostProcessor: 
下面的获取可以让你明白什么情况下也使用了BeanFactoryPostProcessor,或者BeanFactoryPostProcessor的作用。 
view plaincopy to clipboardprint?
  1. ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(  
  2.         new ClassPathResource("/META-INF/spring/bfpp2-context.xml")  
  3. );  
  4. BeanFactoryPostProcessor bfpp = (BeanFactoryPostProcessor)beanFactory.getBean("bfpp");  
  5. bfpp.postProcessBeanFactory(beanFactory);  
  6.   
  7. System.out.println(beanFactory.getBean("simpleBean"));  



编写一个BeanFactoryPostProcessor:
view plaincopy to clipboardprint?
  1. package cn.partner4java.beanfactorypostprocessor;  
  2.   
  3. import java.util.HashSet;  
  4. import java.util.Set;  
  5.   
  6. import org.springframework.beans.BeansException;  
  7. import org.springframework.beans.factory.BeanNameAware;  
  8. import org.springframework.beans.factory.config.BeanDefinition;  
  9. import org.springframework.beans.factory.config.BeanDefinitionVisitor;  
  10. import org.springframework.beans.factory.config.BeanFactoryPostProcessor;  
  11. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;  
  12. import org.springframework.util.StringValueResolver;  
  13.   
  14. /** 
  15. * 删除非法字符的反调器 
  16. * @author partner4java 
  17. * 
  18. */  
  19. public class ObscenityRemovingBeanFactoryPostProcessor implements  
  20.         BeanFactoryPostProcessor, BeanNameAware {  
  21.     /** bean的名称 */  
  22.     private String name;  
  23.     /** 注册过滤文字 */  
  24.     private Set<String> obscenities;  
  25.     /** 返回过滤掉的文字 */  
  26.     private Set<String> obscenitiesRemoved;  
  27.       
  28.     public ObscenityRemovingBeanFactoryPostProcessor() {  
  29.         this.obscenities = new HashSet<String>();  
  30.         this.obscenitiesRemoved = new HashSet<String>();  
  31.     }  
  32.   
  33.   
  34.     /** 
  35.      * 主要业务处理。 
  36.      */  
  37.     public void postProcessBeanFactory(  
  38.             ConfigurableListableBeanFactory beanFactory) throws BeansException {  
  39.         String[] beanNames = beanFactory.getBeanDefinitionNames();  
  40.           
  41.           
  42.           
  43.         //下面两个类是用来替换参数的  
  44.         //Simple strategy interface for resolving a String value.  
  45.         StringValueResolver valueResolver = new StringValueResolver() {  
  46.             public String resolveStringValue(String strVal) {  
  47.                 if(isObscene(strVal)){  
  48.                     obscenitiesRemoved.add(strVal);  
  49.                     return "****";  
  50.                 }  
  51.                 return strVal;  
  52.             }  
  53.         };  
  54.         //Visitor class for traversing BeanDefinition objects, in particular the property values and constructor argument values contained in them, resolving bean metadata values.   
  55.         //Used by PropertyPlaceholderConfigurer to parse all String values contained in a BeanDefinition, resolving any placeholders found.  
  56.         BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);  
  57.           
  58.           
  59.           
  60.         for(String beanName:beanNames){  
  61.             if(beanName.equals(this.name)) continue;  
  62.               
  63.             //如果不是实体就应该是参数,获取参数  
  64.             BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);  
  65.   
  66.             visitor.visitBeanDefinition(beanDefinition);  
  67.         }  
  68.         beanFactory.registerSingleton("obscenitiesRemoved"this.obscenitiesRemoved);  
  69.     }  
  70.       
  71.     private boolean isObscene(Object value) {  
  72.         String potentialObscenity = value.toString().toUpperCase();  
  73.         return this.obscenities.contains(potentialObscenity);  
  74.     }  
  75.       
  76.     public void setObscenities(Set<String> obscenities) {  
  77.         this.obscenities.clear();  
  78.         for(String obscentity:obscenities){  
  79.             this.obscenities.add(obscentity.toUpperCase());  
  80.         }  
  81.     }  
  82.   
  83.   
  84.     public void setBeanName(String name) {  
  85.         this.name = name;  
  86.     }  
  87.   
  88. }  

配置文件:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.     <bean id="bfpp" class="cn.partner4java.beanfactorypostprocessor.ObscenityRemovingBeanFactoryPostProcessor">  
  8.         <property name="obscenities">  
  9.             <set>  
  10.                 <value>winky</value>  
  11.                 <value>bum</value>  
  12.             </set>  
  13.         </property>  
  14.     </bean>  
  15.     <bean id="simpleBean" class="cn.partner4java.beanfactorypostprocessor.SimpleBean">  
  16.         <property name="connectionString" value="bollocks"/>  
  17.         <property name="password" value="winky"/>  
  18.         <property name="username" value="bum"/>  
  19.     </bean>                  
  20.       
  21. </beans>  

调用:
view plaincopy to clipboardprint?
  1. ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(  
  2.         new ClassPathResource("/META-INF/spring/spring-beanfactorypostprocessor.xml")  
  3. );  
  4. BeanFactoryPostProcessor bfpp = (BeanFactoryPostProcessor)beanFactory.getBean("bfpp");  
  5. bfpp.postProcessBeanFactory(beanFactory);  
  6.   
  7. SimpleBean simpleBean = (SimpleBean) beanFactory.getBean("simpleBean");  
  8. System.out.println(simpleBean);  
  9. System.out.println(beanFactory.getBean("obscenitiesRemoved"));  

后台打印: 
SimpleBean{password='****', username='****', connectionString='bollocks'} 
[bum, winky] 










7JavaBean的属性修改器 
Spring使用内建的PropertyEditor将String样式的各个属性转换成正确的类型。 

Spring中的PropertyEditor实现类: 
ByteArrayPropertyEditor:PropertyEditor将String值转换为byte数组。 

ClassEditor:ClassEditor将全命名的类名称转换为类实例。使用此PropertyEditor时,注意不要在全类名两边包含不相关的空格。 

CustomBooleanEditor:此自定义editor用于boolean值,处理以UI为中心的代码,他能解析Boolean值的不同String表示。 

CustomCollectionEditor:此PropertyEditor用于创建Java集合框架或者数组的任意类型。 

CustomDateEditor:与CustomBooleanEditor类相似,与PropertyEditor实现类用于控制器的initBinder方法,使应用程序可以解析出入的制定格式的日期为java.util.Date. 

CustomNumberEditor:PropertyEditor实现类将字符串转换为Integer、Long、BigDecimal或者其他任意数据类型子类。 

FileEditor:FileEditor将字符串文件路径转换为File实例,Spring不会检测文件或者目录是否存在。 

InputStreamEditor:此为一个InputStream对象。注意PropertyEditor是你了反射的。他只能转换字符串为InputStream对象。在内部,通过为Resource实例化一个临时的ResourceEditor来完成转换。 

LocaleEditor:LocalEditor实现将表示区域的字符串(如en_GB)转换为一个java.util.Locale实例。 

PatternEditor:ResourceEditor转换正规表达式为一个java.util.regex.Pattern实例。 

PropertiesEditor:PropertiesEditor类转换键值对形式的字符串,key1=hello为java.util.Properties,并使用相应的属性配置。 

StringArrayPropertyEditor:StringArrayPropertyEditor类转换逗号为分割字符串元素列表为字符串数组。 

StringTrimmerEditor:用于删除字符串两边的空格,并转换每一个字符串元素为null。 
Property editor that trims Strings. 
Optionally allows transforming an empty string into a null value. Needs to be explictly registered, e.g. for command binding. 

URLEditor:将URL字符串表示转换为java.net.URL实例。 


(这些属性修改器都是可以手工编写定制的) 






8BeanPostProcessor类 

在Spring实例化bean的前后执行一些附加操作。 

有时,你会发现需要立刻在Spring实例化一个bean的前后执行一些附件操作。这些操作可以简单到修改一个bean,也可以复杂到返回一个完全不同的对象。 
BeanPostProcessor接口包含两个方法: 
postProcessBeforeInitialization:在Spring调用任何bean的初始化钩子(例如InitializingBean.afterPropertiesSet或者init方法)之前被调用。 
postProcessAfterInitialization:Spring在成功完成嵌入初始化以后调用他。 

例子1: 
我们声明了一个实现了BeanPostProcessor接口的类InitDestroyAnnotationBeanPostProcessor,这个类支持声明式的指定注解规则(默认为JSR 250注解) 
view plaincopy to clipboardprint?
  1. public class SimpleBean {  
  2.   
  3.     @PostConstruct  
  4.     public void initialize() {  
  5.         System.out.println("Initializing bean " + getClass());  
  6.     }  
  7.   
  8.     @PreDestroy  
  9.     public void cleanUp() {  
  10.         System.out.println("Cleaning up bean " + getClass());  
  11.     }  
  12.   
  13. }  


配置:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.       
  8.     <bean id="simpleBean" class="com.apress.prospring2.ch04.bpp.SimpleBean"/>  
  9.     <bean id="bpp" class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">  
  10.         <property name="initAnnotationType" value="javax.annotation.PostConstruct"/>  
  11.         <property name="destroyAnnotationType" value="javax.annotation.PreDestroy"/>  
  12.     </bean>  
  13.   
  14. </beans>  

调用: 
view plaincopy to clipboardprint?
  1. public class SimpleBeanDemo {  
  2.   
  3.     public static void main(String[] args) {  
  4.         ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(  
  5.                 new ClassPathResource("/META-INF/spring/bpp-context.xml")  
  6.         );  
  7.         registerPostProcessor(beanFactory, "bpp");  
  8.   
  9.         SimpleBean sb = (SimpleBean)beanFactory.getBean("simpleBean");  
  10.         System.out.println(sb);  
  11.   
  12.         beanFactory.destroySingletons();  
  13.     }  
  14.   
  15.     private static void registerPostProcessor(ConfigurableListableBeanFactory beanFactory, String beanName) {  
  16.         BeanPostProcessor bpp = (BeanPostProcessor) beanFactory.getBean(beanName);  
  17.         beanFactory.addBeanPostProcessor(bpp);  
  18.     }  
  19.   
  20. }  





例子2:自己实现一个BeanPostProcessor接口(改变bean的一个字段数据) 
(例子的实现是像上面的例子一样,自己定义一个时间注解的实现)
view plaincopy to clipboardprint?
  1. package cn.partner4java.beanpostprocessor;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. /** 
  9. * 声明一个运行时字段注解 
  10. * @author partner4java 
  11. * 
  12. */  
  13. @Retention(RetentionPolicy.RUNTIME)  
  14. @Target(ElementType.FIELD)  
  15. public @interface TimeStamp {  
  16. }  
view plaincopy to clipboardprint?
  1. package cn.partner4java.beanpostprocessor;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import javax.annotation.PostConstruct;  
  6. import javax.annotation.PreDestroy;  
  7.   
  8. /** 
  9. * 指定交给Spring管理的bean 
  10. * @author partner4java 
  11. * 
  12. */  
  13. public class SimpleBean {  
  14.     //自定义的注解  
  15.     @TimeStamp  
  16.     Date createDate;  
  17.       
  18.     //spring中InitDestroyAnnotationBeanPostProcessor实现对bean init替代的注解  
  19.     @PostConstruct  
  20.     public void initialize(){  
  21.         System.out.println("initialize: " + getClass());  
  22.     }  
  23.       
  24.     //spring中InitDestroyAnnotationBeanPostProcessor实现对bean destory替代的注解  
  25.     @PreDestroy  
  26.     public void cleanup(){  
  27.         System.out.println("cleanup: " + getClass());  
  28.     }  
  29.   
  30.     @Override  
  31.     public String toString() {  
  32.         return "SimpleBean [createDate=" + createDate + "]";  
  33.     }  
  34.       
  35. }  



编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期:
view plaincopy to clipboardprint?
  1. package cn.partner4java.beanpostprocessor;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.util.Date;  
  5.   
  6. import org.springframework.beans.BeansException;  
  7. import org.springframework.beans.factory.config.BeanPostProcessor;  
  8. import org.springframework.util.ReflectionUtils;  
  9.   
  10. /** 
  11. * 编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期 
  12. * @author partner4java 
  13. * 
  14. */  
  15. public class TimestampingBeanPostProcessor implements BeanPostProcessor {  
  16.   
  17.     public Object postProcessBeforeInitialization(final Object bean, String beanName)  
  18.             throws BeansException {  
  19.         ReflectionUtils.doWithFields(bean.getClass(),   
  20.                 new ReflectionUtils.FieldCallback() {  
  21.                     public void doWith(Field field) throws IllegalArgumentException,  
  22.                             IllegalAccessException {  
  23.                         field.set(bean, new Date());  
  24.                     }  
  25.                 }, new ReflectionUtils.FieldFilter() {  
  26.                     public boolean matches(Field field) {  
  27.                         return field.getType() == Date.class && field.getAnnotation(TimeStamp.class) != null;  
  28.                     }  
  29.                 });  
  30.           
  31.         return bean;  
  32.     }  
  33.   
  34.     public Object postProcessAfterInitialization(Object bean, String beanName)  
  35.             throws BeansException {  
  36.         return bean;  
  37.     }  
  38.   
  39. }  

配置文件:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.       
  8.     <bean id="simpleBean" class="cn.partner4java.beanpostprocessor.SimpleBean"/>  
  9.     <bean id="bpp1" class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">  
  10.         <property name="initAnnotationType" value="javax.annotation.PostConstruct"/>  
  11.         <property name="destroyAnnotationType" value="javax.annotation.PreDestroy"/>  
  12.     </bean>  
  13.     <bean id="bpp2" class="cn.partner4java.beanpostprocessor.TimestampingBeanPostProcessor"/>  
  14.   
  15. </beans>  

调用:
view plaincopy to clipboardprint?
  1. package cn.partner4java.beanpostprocessor;  
  2.   
  3. import javax.annotation.PreDestroy;  
  4.   
  5. import org.springframework.beans.factory.config.BeanPostProcessor;  
  6. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;  
  7. import org.springframework.beans.factory.xml.XmlBeanFactory;  
  8. import org.springframework.core.io.ClassPathResource;  
  9.   
  10. public class SimpleBeanDemo {  
  11.   
  12.     public static void main(String[] args) {  
  13.         ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(  
  14.                 new ClassPathResource("/META-INF/spring/spring-beanpostprocessor.xml")  
  15.         );  
  16.         registerPostProcessor(beanFactory, "bpp1");  
  17.         registerPostProcessor(beanFactory, "bpp2");  
  18.   
  19.         SimpleBean sb = (SimpleBean)beanFactory.getBean("simpleBean");  
  20.         System.out.println(sb);  
  21.   
  22.         //@PreDestroy是被这个方法调用执行的  
  23.         beanFactory.destroySingletons();  
  24.     }  
  25.   
  26.     private static void registerPostProcessor(ConfigurableListableBeanFactory beanFactory, String beanName) {  
  27.         BeanPostProcessor bpp = (BeanPostProcessor) beanFactory.getBean(beanName);  
  28.         beanFactory.addBeanPostProcessor(bpp);  
  29.     }  
  30.   
  31. }  
  32. //后台打印:  
  33. //initialize: class cn.partner4java.beanpostprocessor.SimpleBean  
  34. //SimpleBean [createDate=Tue Nov 15 16:18:33 CST 2011]  
  35. //cleanup: class cn.partner4java.beanpostprocessor.SimpleBean  





例子3: 
Spring自带的简单支持,例子中完全修改了一个bean的类型,从Dependency类转变为了String类型的字符串。(改变一个bean的类型) 
(org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor) 
(继承public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor。 
这让我们使用这个回调处理适配器来实现能够预测回调处理bean的类型的BeanPostProcessor接口) 

我们在下面的定义中指定了一个自动关联的注解,但是我们系统中并没有String类型的dependency关联,只要一个Dependency类交给了Spring。
view plaincopy to clipboardprint?
  1. public class SimpleBean {  
  2.     @Timestamp  
  3.     Date creationDate;  
  4.       
  5.     @Autowired  
  6.     String dependency;  
  7.   
  8.     @PostConstruct  
  9.     public void initialize() {  
  10.         System.out.println("Initializing bean " + getClass());  
  11.     }  
  12.   
  13.     @PreDestroy  
  14.     public void cleanUp() {  
  15.         System.out.println("Cleaning up bean " + getClass());  
  16.     }  
  17.   
  18.     @Override  
  19.     public String toString() {  
  20.         return "Bean was created at " + this.creationDate + " with " + this.dependency;  
  21.     }  
  22. }  


我们修改bean的类型:
view plaincopy to clipboardprint?
  1. public class TypedDependencyBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {  
  2.   
  3.     public Class predictBeanType(Class beanClass, String beanName) {  
  4.         if (beanClass.equals(Dependency.class)) {  
  5.             return String.class;  
  6.         }  
  7.         return beanClass;  
  8.     }  
  9.   
  10.     public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {  
  11.         if (bean.getClass().equals(Dependency.class)) {  
  12.             return "Hello, world";  
  13.         }  
  14.         return bean;  
  15.     }  
  16.   
  17.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  18.         return bean;  
  19.     }  
  20. }  


配置:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.   
  8.     <bean id="dependency" class="com.apress.prospring2.ch04.bpp.Dependency"/>  
  9.     <bean id="simpleBean" class="com.apress.prospring2.ch04.bpp.SimpleBean"/>  
  10.     <bean id="bpp" class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">  
  11.         <property name="initAnnotationType" value="javax.annotation.PostConstruct"/>  
  12.         <property name="destroyAnnotationType" value="javax.annotation.PreDestroy"/>  
  13.     </bean>  
  14.     <bean id="bpp2" class="com.apress.prospring2.ch04.bpp.TimestampingBeanPostProcessor"/>  
  15.     <bean id="bpp3" class="com.apress.prospring2.ch04.bpp.TypedDependencyBeanPostProcessor"/>  
  16.     <bean id="bpp4" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>  
  17.   
  18. </beans>  









9Spring ApplicationContext 

ApplicationContext是对BeanFactory的扩展:他提供相同的功能,但却减少了与之交互所需编写的代码,并且还新增了额外的功能。 
ApplicationContext的主要功能是为构建你的应用程序提供一个更加丰富的框架。 
ApplicationContext最大的好处在与他允许你完全声明性的方法配置和管理Spring以及Spring下的资源。 
国际化 
事件发布 
资源的管理和访问 
增加的生命周期接口 
改进了的基础设施组件自动化配置 




ApplicationContext的实现类: 
FileSystemXmlApplicationContext:可以在文件系统中应用程序有权访问的任何位置加载。 
ClasspathXmlApplicationContext:可以从classpath上任何位置加载配置,这在你需要将配置文件跟一些类文件一起打包在一个JAR文件内时会很有用处。 
XmlWebApplicationContext:是专门在Web应用环境中使用的,通过使用ContextLoaderListener或者ContextLoaderServlet,你可以为你的Web应用自动加载ApplicationContext配置。 




使用ApplicationContextAware: 
一个bean可以实现BeanFactoryAware接口的方式获得一个他所在BeanFactory的引用。同样,也可以通过实现ApplicationContextAware接口获得他在ApplicationContext的引用。
view plaincopy to clipboardprint?
  1. public class ContextAwareDemo implements ApplicationContextAware {  
  2.     private ApplicationContext ctx;  
  3.   
  4.     public void setApplicationContext(ApplicationContext applicationContext)  
  5.             throws BeansException {  
  6.         ctx = applicationContext;  
  7.     }  
  8.   
  9.     public static void main(String[] args) {  
  10.         ApplicationContext ctx = new ClassPathXmlApplicationContext(  
  11.                 "/META-INF/spring/acdemo1-context.xml");  
  12.   
  13.         ContextAwareDemo demo = (ContextAwareDemo) ctx.getBean("contextAware");  
  14.         demo.displayAppContext();  
  15.     }  
  16.   
  17.     public void displayAppContext() {  
  18.         System.out.println(ctx);  
  19.     }  
  20.   
  21. }  

配置:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.       
  8.     <bean id="contextAware" class="com.apress.prospring2.ch04.context.ContextAwareDemo"/>  
  9.   
  10.   
  11. </beans>  






控制bean的初始化: 
<bean .. lazy-init="false" ../> 



使用基于注解的配置: 
@Component :基本类型,使用注解的类将成为Spring的bean 
@Controller :作为一个Spring MVC支持的控制器(带有这个注解的类会成为Spring MVC控制器) 
@Repository :表示一个库,如一个数据库访问对象(将获得自动异常转换) 
@Service :标记实现应用程序部分业务逻辑的类 

指明要扫描注解的路径: 
<context:component-scan base-package="com.apress.prospring2.ch04.annotations"/> 


Spring中过滤器的类型: 
annotation:设置另一个注解类型,你讲使用他表示你希望Spring扫描的类。 
assignable:为应该赋值的类指定完整的类名。 
regex:为应该匹配的类指定正则表达式。 
aspectj:使用横切点类型的表达式指定锁使用类的全名。 

demo:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:context="http://www.springframework.org/schema/context"  
  4.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.        xsi:schemaLocation="  
  6.                 http://www.springframework.org/schema/beans  
  7.                 http://www.springframework.org/schema/beans/spring-beans.xsd  
  8.                 http://www.springframework.org/schema/context  
  9.                 http://www.springframework.org/schema/context/spring-context.xsd">  
  10.   
  11.     <context:component-scan base-package="com.apress.prospring2.ch04.annotations">  
  12.         <context:include-filter type="annotation" expression="com.apress.prospring2.ch04.annotations.Magic"/>  
  13.         <context:include-filter type="assignable" expression="com.apress.prospring2.ch04.annotations.ComponentMarker"/>  
  14.         <context:include-filter type="aspectj" expression="* void com.apress..annotations.*Service*(..)"/>  
  15.     </context:component-scan>  
  16.   
  17. </beans>  









使用MessageSource进行国际化: 
123-130页 





使用应用程序事件: 
ApplicationContext还可以作为中间人发布和接受事件。 

例子: 
event
view plaincopy to clipboardprint?
  1. public class MessageEvent extends ApplicationEvent {  
  2.     private static final long serialVersionUID = -6786033091498612636L;  
  3.     private String message;  
  4.   
  5.     public MessageEvent(Object source, String message) {  
  6.         super(source);  
  7.         this.message = message;  
  8.     }  
  9.   
  10.     public String getMessage() {  
  11.         return message;  
  12.     }  
  13. }  

Listener:
view plaincopy to clipboardprint?
  1. public class MessageEventListener implements ApplicationListener {  
  2.     public void onApplicationEvent(ApplicationEvent event) {  
  3.         if (event instanceof MessageEvent) {  
  4.             MessageEvent messageEvent = (MessageEvent)event;  
  5.             System.out.println("Received " + messageEvent.getMessage() +  
  6.                     " from " + messageEvent.getSource());  
  7.         }  
  8.     }  
  9. }  

调用:
view plaincopy to clipboardprint?
  1. public class EventPublisherDemo implements ApplicationContextAware {  
  2.   
  3.     private ApplicationContext ctx;  
  4.   
  5.     public static void main(String[] args) {  
  6.         ApplicationContext ctx = new ClassPathXmlApplicationContext(  
  7.                 "/META-INF/spring/eventsdemo1-context.xml");  
  8.   
  9.         EventPublisherDemo pub = (EventPublisherDemo) ctx.getBean("publisher");  
  10.         pub.publish("Hello World!");  
  11.         pub.publish("The quick brown fox jumped over the lazy dog");  
  12.     }  
  13.   
  14.     public void setApplicationContext(ApplicationContext applicationContext)  
  15.             throws BeansException {  
  16.         this.ctx = applicationContext;  
  17.   
  18.     }  
  19.   
  20.     public void publish(String message) {  
  21.         ctx.publishEvent(new MessageEvent(this, message));  
  22.     }  
  23.   
  24. }  

配置:
view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.       
  8.     <bean id="publisher" class="com.apress.prospring2.ch04.event.EventPublisherDemo"/>  
  9.     <bean class="com.apress.prospring2.ch04.event.MessageEventListener"/>  
  10.   
  11. </beans>  

(我们并不需要特殊的配置将MessageEventListener注册到ApplicationContext上,他是被Spring自动挑选出来的) 








访问资源: 
不管一个文件是保存在文件系统上、classpath上或者远程服务器上,你的应用程序都能以相同的方式访问到他。 

核心是Resource接口。
view plaincopy to clipboardprint?
  1. public class ResourceDemo {  
  2.   
  3.     public static void main(String[] args) throws Exception{  
  4.         ApplicationContext ctx = new ClassPathXmlApplicationContext(  
  5.             "/META-INF/spring/resourcesdemo1-context.xml");  
  6.   
  7.         Resource res1 = ctx.getResource("file:///tmp");  
  8.         displayInfo(res1);  
  9.         Resource res2 = ctx.getResource("classpath:com/apress/prospring2/ch04/pe/Complex.class");  
  10.         displayInfo(res2);  
  11.         Resource res3 = ctx.getResource("http://www.google.co.uk");  
  12.         displayInfo(res3);  
  13.     }  
  14.   
  15.     private static void displayInfo(Resource res) throws Exception{  
  16.         System.out.println(res.getClass());  
  17.         System.out.println(res.getURL().getContent());  
  18.         System.out.println("");  
  19.     }  
  20.   
  21. }  

原创粉丝点击