1. 程式人生 > >Spring的方法注入

Spring的方法注入

當一個Bean依賴的Bean和自己生命週期不同的時候:如Bean A依賴Bean B,Bean A 是singleton,如果需要在Bean A每次用到Bean B的時候都用一個Bean B的新的例項,通過在配置檔案中通過 property或者 contructor-arg是不能實現的.這時候只能在Bean A中用Bean B的時候動態得到.通常的做法有兩種:

1,Bean A實現 ApplicationContextAware, Spring初始化的時候會將 ApplicationContext 傳給Bean A,Bean A通過getBean("BeanB")方法每次得到Bean B.("BeanB"最好不要hardcode,通過property傳入)例:

public class ContextAwareBean implements ApplicationContextAware {
    protected static final Log log = LogFactory.getLog(AnotherBean.class);
    private String anotherBeanName;
    private ApplicationContext applicationContext;
   
    public String getAnotherBeanName() {
        return anotherBeanName;
    }
    public void setAnotherBeanName(String anotherBeanName) {
        this.anotherBeanName = anotherBeanName;
    }
    public void process() {
        log.info("process applicationContext " + applicationContext);
        AnotherBean anotherBean = createAnotheBean();
        anotherBean.doSth();
       
    }
    protected AnotherBean createAnotheBean() {
   
    return this.applicationContext.getBean(anotherBeanName, AnotherBean.class);
    }
    public void setApplicationContext(ApplicationContext applicationContext){
        log.info("setApplicationContext " + applicationContext);
        this.applicationContext = applicationContext;
    }
}
 public class AnotherBean {
    protected static final Log log = LogFactory.getLog(AnotherBean.class);
    public String doSth(){
        log.info("AnotherBean.doSth");
        return "do something";
    }
}

<bean id="AnotherBean" class="com.test.spring.di.mtddi.AnotherBean"  scope="prototype"/>
   
    <bean id="ContextAwareBean" class="com.test.spring.di.mtddi.ContextAwareBean" >
        <property name="anotherBeanName" value="AnotherBean"/>
    </bean>
2,方法注入:在Bean A中定義一個方法,返回型別是Bean B,在配置檔案中通過"lookup-method"告訴Spring動態覆蓋該方法,並返回Bean B的一個例項:
public  abstract class ReplacedBean {
protected static final Log log = LogFactory.getLog(ReplacedBean.class);
   
    public void process() {
       
        AnotherBean anotherBean = createAnotheBean();
        anotherBean.doSth();
       
    }
    protected abstract AnotherBean createAnotheBean();
   
}

<bean id="AnotherBean" class="com.test.spring.di.mtddi.AnotherBean"  scope="prototype"/>

<bean id="ReplacedBean" class="com.test.spring.di.mtddi.ReplacedBean" >
        <lookup-method name="createAnotheBean" bean="AnotherBean"/>
    </bean>
客戶端程式碼:
public class MtddiClient {
    private static BeanFactory factory;
    private static ApplicationContext ctx;
    static {
        Resource resource = new ClassPathResource("conf/mtddiAppcontext.xml");
        factory = new XmlBeanFactory(resource);
       
        ctx = new ClassPathXmlApplicationContext("conf/mtddiAppcontext.xml");
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        /*不能通過bean factory的方式得到bean
        ContextAwareBean bean = (ContextAwareBean) factory.getBean("ContextAwareBean");
        bean.process();
        */
        //ContextAwareBean 只能從ApplicationContext獲得bean
        //ContextAwareBean bean = (ContextAwareBean) ctx.getBean("ContextAwareBean");
        //bean.process();
                
        ReplacedBean bean1 = (ReplacedBean) factory.getBean("ReplacedBean");
        bean1.process();
    }
}
*對於實現ApplicationContextAware的Bean,必須用 ApplicationContext的getBean方法.對於方法注入(lookup-method方式):用BeanFactory和ApplicationContext的getBean都可以.如果要用BeanFactory,應該實現BeanFactoryAware:
public class BeanFactoryAwareBean implements BeanFactoryAware {
    protected static final Log log = LogFactory.getLog(BeanFactoryAwareBean.class);
    private String anotherBeanName;
   
    private BeanFactory beanFactory;
   
    public String getAnotherBeanName() {
        return anotherBeanName;
    }
    public void setAnotherBeanName(String anotherBeanName) {
        this.anotherBeanName = anotherBeanName;
    }
    public void process() {
        log.info("process beanFactory " + beanFactory);
        AnotherBean anotherBean = createAnotheBean();
        anotherBean.doSth();      
    }
    protected AnotherBean createAnotheBean() {
   
    return this.beanFactory.getBean(anotherBeanName, AnotherBean.class);
    }
   
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;       
    }
}
兩種方法的比較:理論上來講,第二種方法更體現了IoC的思想,而且在bean類裡面沒有依賴到Spring,只是一個POJO.客戶端在使用它的時候可以是依靠Spring配置(lookup-method)來使用,也可以通過提供實現類來完成呼叫.