1. 程式人生 > >Spring(三)Bean繼續入門

Spring(三)Bean繼續入門

throws 信息 location set urn startup 應用程序 etc tco

一、Aware相關接口

對於應用程序來說,應該盡量減少對Sping Api的耦合程度,然而有些時候為了運用Spring所提供的一些功能,有必要讓Bean了解Spring容器對其進行管理的細節信息,如讓Bean知道在容器中是以那個名稱被管理的,或者讓Bean知道BeanFactory或者ApplicationContext的存在,也就是產讓該Bean可以取得BeanFactory或者ApplicationContext的實例,如果Bean可以意識到這些對象,那麽就可以在Bean的某些動作發生時,做一些如事件發布等操作。

1.1、Spring提供一些Aware接口:

beanNameAware接口:

如果某個bean需要訪問配置文件中本身bean的id屬性,這個Bean類通過實現該接口,在依賴關系確定之後,初始化方法之前,提供回調自身的能力,從而獲得本身bean的id屬性,該接口提供了void setBeanName(String name)方法實現,需要指出的是該方法的name參數就是該bean的id屬性,加調該setBeanName方法可以讓bean獲取得自身的id屬性

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繼續入門