如何包装Spring Beans

6

我是一个关于Spring框架的新手。

我的问题是:如何在运行时将bean包装到另一个类中?

对于每个数据结构和Java类型,我都有以下类:

@Component
    public class ByteCodec extends Codec<Byte> {
    public ByteCodec() {
        super(Byte.class);
    }

    public void encode(... buffer, Byte object) {
        buffer.writeByte(object);
    }

    public Byte decode(... buffer) {
        return buffer.readByte();
    }
}

并且这个类是一个被管理的Spring单例。 我需要用下一个类来包装这个编解码器:

class OptionalCodec<T> extends Codec<Boolean> {
    public OptionalCodec(Codec<T> clazz) {
    }
    ... some implementation of encode && decode method's ...
}

我该如何做到这一点?提示:我希望对每个Codec实例自动进行运行时换行。

还有,如何扩展Autowired注释,就像这样:

@AutowireCodec(targetClass=Integer.class, canBeNull=false)
private Codec<Integer> codec;

如何使用映射注册所有运行时创建的编解码器:

Map<*MyCodecInfoClass*, Codec>

感谢您的回复!
1个回答

1

Spring允许您直接按类型和泛型注入bean,因此对于您的用例,我认为没有必要创建新的Autowired注释。您可以像这样简单地使用现有的@Autowired:

@Autowired
private Codec<Byte> codec;

请记住,如果您为相同的泛型类型定义了多个bean,并使用上述代码,则会出现错误,因为存在具有该定义的多个bean。您可以通过注入集合而不是单个对象来解决这个问题,例如:

@Autowired
private List<Codec<Byte>> byteCodecs;

如果您想要所有编解码器,无论其通用类型如何,只需执行以下操作:

@Autowired
private List<Codec<?>> allCodecs;

关于您提出的实例包装问题,我不确定我是否完全理解您试图实现什么,但是您可以像我上面所述一样将编解码器注入到另一个编解码器中,或者您可以查看Spring AOP并使用它来包装对您的bean的调用:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html


我仍然不确定OptionalCodec的目的是什么,因为它会在编码/解码方法上接受布尔值。 OptionalCodec是与基本Codec接口不同的类,所以如果您这样做:

@Autowired
private OptionalCodec<Byte> codec;

将可选字节编解码器注入。如果您这样做:
@Autowired
private Codec<Byte> codec;

将注入原始的Byte编解码器。但如果您这样做:
@Autowired
private Codec<Boolean> codec;

它将匹配所有的 OptionalCodec bean(因为 OptionalCodec 的类型签名是 Codec<Boolean>),但会抛出错误,因为它无法选择一个单一的 bean。
话虽如此,如果您确实需要微调相同类型的 bean 的自动装配,我建议您查看 Spring 文档中相关部分,其中解释了像 @Primary@Qualifier 这样的注释,并让您完全做到这一点: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-autowired-annotation-qualifiers

谢谢您的回答!非常抱歉我的英语。。我想要添加一些像beanpostprocessor的东西来处理所有Codec beans,并将codec对象实例包装在OptionalCodec中,然后通过新的bean名称在spring容器中进行注册。 ..例如,我有一个byteCodec bean,当单例创建时,我需要处理它并用新名称optionalByteCodec进行包装.. 如何做到这一点? 这是我的包装器方法:http://pastebin.com/CqWiujzA(codecRegistry是简单的Map<*CodecInfo*,Codec instance>.. clazz-是codec支持的目标类,codec是codec实例.. 也许spring有管理注册表? - Shift
需要自定义@Autowired注释:Spring如何理解我需要自动装配哪种编解码器?byteCodec还是optionalByteCodec? - Shift
您将无法使用BeanPostProcessor定义新的bean,只能在其初始化之前和/或之后处理现有的bean。这意味着,如果您将包装器实现为BeanPostProcessor,则最终将得到相同数量的bean,但所有bean都被包装在OptionalCodecs中,而不是原始bean和可选项作为不同的bean。 - Ricardo Illgen
为了修改(或添加)bean的定义,你可以使用BeanFactoryPostProcessor来实现,但请记住,这个操作是在任何bean被实例化之前执行的,所以你必须直接处理bean的定义,这可能会变得非常混乱且容易出错。你真的需要同时处理包装和未包装的实例吗?请查看答案中的附加信息。希望这能稍微澄清一些! - Ricardo Illgen
我解决了这个问题:从核心项目中删除Spring容器,使用自己的CodecRegistry和编解码器注册服务;) 现在所有的编解码器都存储在XML文件中。 - Shift

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接