如何使用@Bean批注配置子bean

时间:2016-09-27 12:22:14

标签: java spring

我想在使用bean的SELECT PERSON_ID, MAX(NAME) as NAME, MIN(GRADE) as GRADE1, MAX(GRADE) as GRADE2 FROM TABLE_A GROUP BY PERSON_ID 类型定义时使用Spring的bean继承。具体来说,让

@Bean

并假设基于xml的配置如下所示:

public class Serwis {
    Integer a;
    Integer b;
    Map<Integer, Integer> m = new HashMap<>();
}

确实创建了包含bean <bean id="absSerwis" class="service.Serwis" p:a="11"> <property name="m"> <map> <entry key="111" value="111"></entry> </map> </property> </bean> <bean id="defSerwis" parent="absSerwis" p:b="12" /> 的深层副本的bean defSerwis;特别是absSerwis的内容被复制。现在,我想使用m注释来定义像defSerwis这样的bean,比如

@Bean

这样做的正确方法是什么?

3 个答案:

答案 0 :(得分:1)

首先,你所描述的并不是实际发生的事情。没有深层复制或其他任何东西。让我们首先研究Spring在使用parent bean时的作用。 (另请注意,它是关于 bean-definition继承 NOT 类继承!);

鉴于您的配置

<bean id="absSerwis" class="service.Serwis"
      p:a="11">
    <property name="m">
        <map>
            <entry key="111" value="111"></entry>
        </map>
    </property>
</bean>

<bean id="defSerwis" parent="absSerwis"
      p:b="12"
  />

对于defSerwis定义,它采用父absSerwis及其自身的配置并将其合并为完整的bean定义。因此,没有像豆子的深拷贝或副本那样的东西。

Spring最终看到了什么

<bean id="absSerwis" class="service.Serwis"
      p:a="11">
    <property name="m">
        <map>
            <entry key="111" value="111"></entry>
        </map>
    </property>
</bean>

<bean id="defSerwis" class="service.Serwis"
      p:a="11" p:b="12"
      <property name="m">
        <map>
            <entry key="111" value="111"></entry>
        </map>
    </property>
  />

另见参考指南的this section

最简单的方法是创建一个构造父级的方法,然后从那里添加。此方法必须使用@Bean进行注释。

@Configuration
public class MyConfiguration {

    private Serwis baseSerwis() {
        Serwis base =  new Serwis();
        base.setA(11);
        Map map = new HashMap();
        map.put(111, 111);
        base.setM(map);
        return base;
    }

    @Bean
    public Serwis absSerwis() {
        return baseSerwis();
    }

    @Bean
    public Serwis defSerwis() {
        Serwis defSerwis = baseSerwis();
        defSerwis.setB(12);
        return defSerwis;
    }
}

这或多或少相当于xml部分。

答案 1 :(得分:0)

如果您想制作一份深层的物品副本,那么您可以:

1)自己编程。

2)使用java序列化来执行此操作(序列化和反序列化可以创建深层副本),但这要求数据结构中的所有对象都实现可序列化接口。还有其他可用于此的库(例如xStream)。

3)Spring默认只创建一个特定bean的实例(也就是Singleton),你可以用@Prototype对它进行注释,让Spring知道你每次需要时都想得到一个新对象。

答案 2 :(得分:0)

使用构建器+复制方法

public class Serwis {
    Integer a;
    Integer b;
    Map<Integer, Integer> m = new HashMap<>();

    private Serwis(Builder builder) {
        a = builder.a;
        b = builder.b;
        m = builder.m;
    }

    public static Builder builder() {
        return new Builder();
    }

    public Builder copy(Serwis copy) {
        return builder()
            .a(a)
            .b(b)
            .m(m);
    }

    public static final class Builder {
        private Integer a;
        private Integer b;
        private Map<Integer, Integer> m = new HashMap<>();

        private Builder() {
        }

        public Builder a(Integer val) {
            a = val;
            return this;
        }

        public Builder b(Integer val) {
            b = val;
            return this;
        }

        public Builder m(Map<Integer, Integer> val) {
            m.putAll(val);
            return this;
        }

        public Serwis build() {
            return new Serwis(this);
        }
    }
}

配置类如下:

@Autowired
@Qualifier("absSerwis")
private Serwis absSerwis;

@Bean
public Serwis cccSerwis() {
    return absSerwis.copy().build();
}