实例化同一个类的多个Bean与Spring的注解 [英] Instantiating multiple beans of the same class with Spring annotations

查看:1166
本文介绍了实例化同一个类的多个Bean与Spring的注解的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过一个XML配置的Spring bean工厂,我可以很容易地实例化不同的参数相同类的多个实例。我该怎么做注解一样吗?我想是这样的:

  @Component(名字=乔,姓氏=史密斯)
@Component(名字=玛丽,姓氏=威廉姆斯)
公共类Person {/ *等等等等* /}


解决方案

是的,你可以用自定义的BeanFactoryPostProcessor实现的帮助下做到这一点。

下面是一个简单的例子。

假设我们有两个组成部分。一个是另一个的依赖性。

第一部分:

 进口org.springframework.beans.factory.InitializingBean接口;
进口org.springframework.util.Assert; 公共类MyFirstComponent实现的InitializingBean {    私人MySecondComponent ASD;    私人MySecondComponent QWE;    公共无效的afterPropertiesSet()抛出异常{
        Assert.notNull(ASD);
        Assert.notNull(QWE);
    }    公共无效setAsd(MySecondComponent ASD){
        this.asd = ASD;
    }    公共无效setQwe(MySecondComponent QWE){
        this.qwe = QWE;
    }
}

正如你可以看到,没有什么特别之处这个组件。它有MySecondComponent的两个不同的实例依赖。

第二个组成部分:

 进口org.springframework.beans.factory.FactoryBean;
进口org.springframework.beans.factory.annotation.Qualifier;
@Qualifier(值=QWE,ASD)
公共类MySecondComponent实现的FactoryBean {    公共对象的getObject()抛出异常{
        返回新MySecondComponent();
    }    公共类getObjectType(){
        返回MySecondComponent.class;
    }    公共布尔isSingleton(){
        返回true;
    }
}

这是一个有点棘手。这里有两件事情来解释。第一个 - @Qualifier - 注释,其中包含MySecondComponent豆的名字。这是一个标准,但你可以自由地实现自己的。你会看到稍后原因。

提及第二件事是FactoryBean的实现。如果bean实现这个接口,它的目的是创建一些其他情况。在我们的情况下,它与MySecondComponent类型创建实例。

最棘手的部分是BeanFactoryPostProcessor的执行:

 进口的java.util.Map;进口org.springframework.beans.BeansException;
进口org.springframework.beans.factory.annotation.Qualifier;
进口org.springframework.beans.factory.config.BeanFactoryPostProcessor;
进口org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
公共类MyBeanFactoryPostProcessor实现BeanFactoryPostProcessor的{
    公共无效postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory)抛出BeansException {
        地图<弦乐,对象>地图= configurableListableBeanFactory.getBeansWithAnnotation(Qualifier.class);
        对于(Map.Entry的<弦乐,对象>项:map.entrySet()){
            createInstances(configurableListableBeanFactory,entry.getKey(),entry.getValue());
        }    }    私人无效createInstances(
            ConfigurableListableBeanFactory configurableListableBeanFactory,
            串beanName,
            对象豆){
        预选赛资格赛= bean.getClass()getAnnotation(Qualifier.class)。
        对于(字符串名称:extractNames(预选赛)){
            对象newBean = configurableListableBeanFactory.getBean(beanName);
            configurableListableBeanFactory.registerSingleton(name.trim(),newBean);
        }
    }    私有String [] extractNames(预选赛资格赛){
        返回qualifier.value()分裂();
    }
}

这是什么呢?它通过与@Qualifier注解的所有bean,从注释提取物的名称,然后手动创建一个具有指定的名称这种类型的豆类。

下面是Spring配置:

 <?XML版本=1.0编码=UTF-8&GT?;
<豆的xmlns =htt​​p://www.springframework.org/schema/beans
       XMLNS:XSI =htt​​p://www.w3.org/2001/XMLSchema-instance
       XSI:的schemaLocation =htt​​p://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\">    < bean类=MyBeanFactoryPostProcessor/>    < bean类=MySecondComponent/>
    < bean名称=测试类=MyFirstComponent>
        <属性名=ASDREF =ASD/>
        <属性名=QWEREF =QWE/>
    < /豆>< /豆>

最后一件事这里需要注意的是,虽然您可以做您不该,除非它是必须的,因为这是配置的没有真正自然的方式。如果你有类的多个实例,最好坚持使用XML配置。

With an XML configured Spring bean factory, I can easily instantiate multiple instances of the same class with different parameters. How can I do the same with annotations? I would like something like this:

@Component(firstName="joe", lastName="smith")
@Component(firstName="mary", lastName="Williams")
public class Person { /* blah blah */ }

解决方案

Yes, you can do it with a help of your custom BeanFactoryPostProcessor implementation.

Here is a simple example.

Suppose we have two components. One is dependency for another.

First component:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

 public class MyFirstComponent implements InitializingBean{

    private MySecondComponent asd;

    private MySecondComponent qwe;

    public void afterPropertiesSet() throws Exception {
        Assert.notNull(asd);
        Assert.notNull(qwe);
    }

    public void setAsd(MySecondComponent asd) {
        this.asd = asd;
    }

    public void setQwe(MySecondComponent qwe) {
        this.qwe = qwe;
    }
}

As you could see, there is nothing special about this component. It has dependency on two different instances of MySecondComponent.

Second component:

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;


@Qualifier(value = "qwe, asd")
public class MySecondComponent implements FactoryBean {

    public Object getObject() throws Exception {
        return new MySecondComponent();
    }

    public Class getObjectType() {
        return MySecondComponent.class;
    }

    public boolean isSingleton() {
        return true;
    }
}

It's a bit more tricky. Here are two things to explain. First one - @Qualifier - annotation which contains names of MySecondComponent beans. It's a standard one, but you are free to implement your own. You'll see a bit later why.

Second thing to mention is FactoryBean implementation. If bean implements this interface, it's intended to create some other instances. In our case it creates instances with MySecondComponent type.

The trickiest part is BeanFactoryPostProcessor implementation:

import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;


public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        Map<String, Object> map =  configurableListableBeanFactory.getBeansWithAnnotation(Qualifier.class);
        for(Map.Entry<String,Object> entry : map.entrySet()){
            createInstances(configurableListableBeanFactory, entry.getKey(), entry.getValue());
        }

    }

    private void createInstances(
            ConfigurableListableBeanFactory configurableListableBeanFactory,
            String beanName,
            Object bean){
        Qualifier qualifier = bean.getClass().getAnnotation(Qualifier.class);
        for(String name : extractNames(qualifier)){
            Object newBean = configurableListableBeanFactory.getBean(beanName);
            configurableListableBeanFactory.registerSingleton(name.trim(), newBean);
        }
    }

    private String[] extractNames(Qualifier qualifier){
        return qualifier.value().split(",");
    }
}

What does it do? It goes through all beans annotated with @Qualifier, extract names from the annotation and then manually creates beans of this type with specified names.

Here is a Spring config:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="MyBeanFactoryPostProcessor"/>

    <bean class="MySecondComponent"/>


    <bean name="test" class="MyFirstComponent">
        <property name="asd" ref="asd"/>
        <property name="qwe" ref="qwe"/>
    </bean>

</beans>

Last thing to notice here is although you can do it you shouldn't unless it is a must, because this is a not really natural way of configuration. If you have more than one instance of class, it's better to stick with XML configuration.

这篇关于实例化同一个类的多个Bean与Spring的注解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆