Dashboard > OpenSource Project > ... > Spring > 入門 15 - Aware相關介面
OpenSource Project Log In   View a printable version of the current page.
入門 15 - Aware相關介面
Added by 良葛格, last edited by koji lin on Nov 29, 2004  (view change)
Labels: 
(None)

 Spring中提供一些Aware相關介面,像是BeanFactoryAware、 ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等,實作這些 Aware介面的Bean在被初始之後,可以取得一些相對應的資源,例如實作BeanFactoryAware的Bean在初始後,Spring容器將會注入BeanFactory的實例,而實作ApplicationContextAware的Bean,在Bean被初始後,將會被注入 ApplicationContext的實例等等。

 Bean取得BeanFactory、ApplicationContextAware的實例目的是什麼,一般的目的就是要取得一些檔案資源的存取、相關訊息資源或是那些被注入的實例所提供的機制,例如ApplicationContextAware提供了publishEvent()方法,可以支援基於Observer模式的事件傳播機制。

 ApplicationContextAware介面的定義如下:

ApplicationContextAware.java
public interface ApplicationContextAware {
    void setApplicationContext(ApplicationContext context);
}

 我們這邊示範如何透過實作ApplicationContextAware注入ApplicationContext來實現事件傳播,首先我們的HelloBean如下:

HelloBean.java
package onlyfun.caterpillar;

import org.springframework.context.*;
 
public class HelloBean implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    private String helloWord = "Hello!World!";
   
    public void setApplicationContext(ApplicationContext context) {
        this.applicationContext = context;
    }
   
    public void setHelloWord(String helloWord) {
        this.helloWord = helloWord;
    }
   
    public String getHelloWord() {
        applicationContext.publishEvent(
               new PropertyGettedEvent("[" + helloWord + "] is getted"));
        return helloWord;
    }
}

 ApplicationContext會由Spring容器注入,publishEvent()方法需要一個繼承ApplicationEvent的物件,我們的PropertyGettedEvent繼承了ApplicationEvent,如下:

PropertyGettedEvent.java
package onlyfun.caterpillar;

import org.springframework.context.*;

public class PropertyGettedEvent extends ApplicationEvent {
    public PropertyGettedEvent(Object source) {
        super(source);
    }
}

 當ApplicationContext執行publishEvent()後,會自動尋找實作ApplicationListener介面的物件並通知其發生對應事件,我們實作了PropertyGettedListener如下:

PrppertyGettedListener.java
package onlyfun.caterpillar;

import org.springframework.context.*;

public class PropertyGettedListener implements ApplicationListener {
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println(event.getSource().toString());   
    }
}

 Listener必須被實例化,這我們可以在Bean定義檔中加以定義:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="propertyGetterListener" class="onlyfun.caterpillar.PropertyGettedListener"/>

    <bean id="helloBean" class="onlyfun.caterpillar.HelloBean">
        <property name="helloWord"><value>Hello!Justin!</value></property>
    </bean>
</beans>

 我們寫一個測試程式來測測事件傳播的運行:

Test.java
package onlyfun.caterpillar;

import org.springframework.context.*;
import org.springframework.context.support.*;

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
       
        HelloBean hello = (HelloBean) context.getBean("helloBean");
        System.out.println(hello.getHelloWord());
    }
}

 執行結果會如下所示:

log4j:WARN No appenders could be found for logger 
(org.springframework.beans.factory.xml.XmlBeanDefinitionReader).
log4j:WARN Please initialize the log4j system properly.
org.springframework.context.support.ClassPathXmlApplicationContext: 
displayName=[org.springframework.context.support.ClassPathXmlApplicationContext;
hashCode=33219526]; startup date=[Fri Oct 29 10:56:35 CST 2004]; 
root of ApplicationContext hierarchy
[Hello!Justin!] is getted
Hello!Justin!

 以上是以實作事件傳播來看看實作Aware介面取得對應物件後,可以進行的動作,同樣的,您也可以實作ResourceLoaderAware介面:

ResourceLoaderAware.java
public interface ResourceLoaderAware {
    void setResourceLoader(ResourceLoader loader);
}

 實作ResourceLoader的Bean就可以取得ResourceLoader的實例,如此就可以使用它的getResource()方法,這對於必須存取檔案資源的Bean相當有用。

 基本上,Spring雖然提供了這些Aware相關介面,然而Bean上若實現了這些介面,就算是與Spring發生了依賴,從另一個角度來看,雖然您可以直接在Bean上實現這些介面,但您也可以透過setter來完成依賴注入,例如:

HelloBean.java
package onlyfun.caterpillar;

import org.springframework.context.*;

public class HelloBean {
    private ApplicationContext applicationContext;
    private String helloWord = "Hello!World!";
   
    public void setApplicationContext(ApplicationContext context) {
        this.applicationContext = context;
    }
   
    public void setHelloWord(String helloWord) {
        this.helloWord = helloWord;
    }
   
    public String getHelloWord() {
        applicationContext.publishEvent(new PropertyGettedEvent("[" + helloWord + "] is getted"));
        return helloWord;
    }
}

 注意這次我們並沒有實作ApplicationContextAware,我們在程式中可以自行注入ApplicationContext實例:

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
       
HelloBean hello = (HelloBean) context.getBean("helloBean");
hello.setApplicationContext(context);
System.out.println(hello.getHelloWord());

 就Bean而言,降低了對Spring的依賴,可以比較容易從現有的框架中脫離。

Site powered by a free Open Source Project / Non-profit License (more) of Confluence - the Enterprise wiki.
Learn more or evaluate Confluence for your organisation.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.1.5a Build:#411 Mar 16, 2006) - Bug/feature request - Contact Administrators