Spring(三)Bean繼續入門
一、Aware相關接口
對於應用程序來說,應該盡量減少對Sping Api的耦合程度,然而有些時候為了運用Spring所提供的一些功能,有必要讓Bean了解Spring容器對其進行管理的細節信息,如讓Bean知道在容器中是以那個名稱被管理的,或者讓Bean知道BeanFactory或者ApplicationContext的存在,也就是產讓該Bean可以取得BeanFactory或者ApplicationContext的實例,如果Bean可以意識到這些對象,那麽就可以在Bean的某些動作發生時,做一些如事件發布等操作。
1.1、Spring提供一些Aware接口:
beanNameAware接口:
BeanFactoryAware接口:實現了BeanFactoryAware接口的bean,可以直接通過beanfactory來訪問spring的容器,當該bean被容器創建以後,會有一個相應的beanfactory的實例引用,該 接口有一個方法void setBeanFactory(BeanFactory beanFactory)方法通過這個方法的參數創建它的BeanFactory實例,實現了BeanFactoryAware接口,就可以讓Bean擁有訪問Spring容器的能力。缺點:導致代碼與spring的api耦合在一起,這種方式不推薦。
ApplicationContextAware接口:在Bean類被初始化後,將會被註入applicationContext實例,該接口有一個方法,setApplicationContext(ApplicationContext context),使用其參數context用來創建它的applicationContext實例,缺點:導致代碼與spring的api耦合在一起,這種方式不推薦。
1.2、beanNameAware接口:
package com.pb.entity; import org.springframework.beans.factory.BeanNameAware; /* * 實體類實現init方法和BeanNameAware接口 */ public class Hello implements BeanNameAware{ @Override public void setBeanName(String arg0) { System.out.println("回調setBeanName方法 id屬性是"+arg0); } public void init(){ System.out.println("正在執行初始化方法init"); } }
applicationContext.xml
<bean id="hello" class="com.pb.entity.Hello" init-method="init"></bean>
測試類:
package com.pb.demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.pb.entity.Hello; public class HelloTest { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); Hello hello=context.getBean("hello",Hello.class); } }
結果:
回調setBeanName方法 id屬性是hello 正在執行初始化方法init
1.3、BeanFactoryAware接口:
package com.pb.entity; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanNameAware; /* * 實體類實現init方法和BeanNameAware接口 */ public class Hello implements BeanNameAware,BeanFactoryAware{ private BeanFactory bf; @Override public void setBeanName(String arg0) { System.out.println("回調setBeanName方法 id屬性是"+arg0); } public void init(){ System.out.println("正在執行初始化方法init"); } /* * 重寫setBeanFactory方法 * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory) */ @Override public void setBeanFactory(BeanFactory arg0) throws BeansException { this.bf=arg0; } public BeanFactory getBf() { return bf; } }
配置文件不變
測試類:
package com.pb.demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.pb.entity.Hello; public class HelloTest { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); Hello hello=context.getBean("hello",Hello.class); System.out.println("得到beanFactory對象 "+hello.getBf()); } }
結果:
回調setBeanName方法 id屬性是hello 正在執行初始化方法init 得到beanFactory對象 org.springframework.beans.factory.support.DefaultListableBeanFactory@3dc0bb: defining beans [hello]; root of factory hierarchy
1.4、ApplicationContextAware接口:
package com.pb.entity; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanNameAware; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; /* * 實體類實現init方法和BeanNameAware接口 */ public class Hello implements BeanNameAware,BeanFactoryAware,ApplicationContextAware{ private BeanFactory bf; private ApplicationContext context; @Override public void setBeanName(String arg0) { System.out.println("回調setBeanName方法 id屬性是"+arg0); } public void init(){ System.out.println("正在執行初始化方法init"); } /* * 重寫setBeanFactory方法 * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory) */ @Override public void setBeanFactory(BeanFactory arg0) throws BeansException { this.bf=arg0; } public BeanFactory getBf() { return bf; } @Override public void setApplicationContext(ApplicationContext arg0) throws BeansException { this.context=arg0; } public ApplicationContext getContext() { return context; } }
配置文件不變
測試類
package com.pb.demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.pb.entity.Hello; public class HelloTest { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); Hello hello=context.getBean("hello",Hello.class); System.out.println("得到beanFactory對象 "+hello.getBf()); System.out.println("得到的applicationContext對象:"+hello.getContext()); } }
結果:
回調setBeanName方法 id屬性是hello 正在執行初始化方法init 得到beanFactory對象 org.springframework.beans.factory.support.DefaultListableBeanFactory@3dc0bb: defining beans [hello]; root of factory hierarchy 得到的applicationContext對象:org.springframework.context.support.ClassPathXmlApplicationContext@1d04653: startup date [Wed Apr 08 00:43:06 CST 2015]; root of context hierarchy
二、BeanPostProcessor類 和BeanFactoryPostProcessor
對容器中的Bean進行處理
實現BeanPostProcessor接口Bean後處理器
public Object postProcessAfterInitialization(Object arg0, String arg1);在bean初始化之後的操作
public Object postProcessBeforeInitialization(Object arg0, String arg1);在bean初始化之前的操作
第一個參數初始化的Bean第二個參數是Bean 實例的名稱
容器後處理器在容器實例化結束後,對容器進行額外的處理
必須實現BeanFactoryPostProcessor接口,
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
Spring撮提供了很多後窗口處理器如:
PropertyPlaceholderConfigurer:屬性占位符配置器
PropertyOverrideConfigurer:另外一種屬性占位符配置器
2種的區別在與後面一種具有覆蓋的性質
2.1、PropertyPlaceholderConfigurer
是spring內建PropertyEdito,它是beanFactoryPostProcess的實現類
作用:讀取properties配置文件
通過該實現類可以將spring的配置文件某些屬性值配置到properties文件中,從而只要悠 properties的文件,spring的配置文件即可進行相應變動。
使用1.PropertyPlaceholderConfigure修改某個部分的屬性時,不需要打開Spring配置文件,從而保證不會將新的錯誤引入到spring的配置文件中。
優點:可以從主xml配置文件中分離出部分的配置信息,
可以支持多個配置文件,可以將配置文件 分割成多個配置文件,從而降低修改配置文件的風險,
2.2、PropertyOverrideConfigurer
會覆蓋掉XML文件中的配置信息,以.properties屬性文件中的配置為主
如果沒有配置PropertyOverrideConfigurer則使用XML中的配置信息
屬性格式:
beanName.property=value
其中beanName是springxml配置方便就近中的bean id屬性,value是屬性的值,對於多個properties文件,通過locations屬性來進行指定
三、自定義屬性編輯器
應用場景:
類型無法識別,如日期等
實現
繼承PropertyEditorSupport
重寫setAsText()方法
package com.pb.entity; import java.util.Date; public class AppDate { private Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }
自定義編輯器
package com.pb.entity; import java.beans.PropertyEditorSupport; import java.text.ParseException; import java.text.SimpleDateFormat; public class CustomerProperty extends PropertyEditorSupport { private String format; @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat sdf=new SimpleDateFormat(format); //super.setAsText(text); try { //轉換對象,能過setValue方法重新賦值 this.setValue(sdf.parse(text)); } catch (ParseException e) { e.printStackTrace(); } } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } }
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <!--定義bean的類為自定義編輯器 --> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <!-- 屬性 --> <property name="customEditors"> <!-- map --> <map> <!-- key為日期 --> <entry key="java.util.Date"> <!--配置map的value --> <bean class="com.pb.entity.CustomerProperty"> <!-- 配置屬性 --> <property name="format" value="yyyy-MM-dd"></property> </bean> </entry> </map> </property> </bean> <!--配置AppDate的bean --> <bean id="appDate" class="com.pb.entity.AppDate"> <property name="date"> <value>2014-4-8</value> </property> </bean> </beans>
測試類:
package com.pb.demo; import java.text.SimpleDateFormat; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.pb.entity.AppDate; public class Demo { /** * @param args */ public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); AppDate appDate=context.getBean("appDate",AppDate.class); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); System.out.println(sdf.format(appDate.getDate())); } }
Spring(三)Bean繼續入門