Spring的方法注入

来源:互联网 发布:韶关网络问政平台 编辑:程序博客网 时间:2024/04/30 10:40

当一个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)来使用,也可以通过提供实现类来完成调用.
原创粉丝点击