java 枚举类如何获取spring管理的Bean对象

1.情景展示

  向枚举类中注入spring管理的bean对象虽然不常见,但是,也有它对应的使用场景,如何实现?

2.原因分析

  以springboot为例,可像普通类那样通过注解@Autowire或@Resource注入对象。

  如上图所示,在枚举类中也是可以使用@Resource或@Autowired注入对象,一开始我以为不可以,后来发现其实也是可以哒;

  只不过,平常我们在类中注入对象是写在类的最前面(作为类的私有属性),而在枚举中,需遵循:枚举对象在最上面,私有属性在下面;

  这就会出现一个问题,因为枚举类在最上面,而注入的对象在下面(代码先后顺序问题),所以,我们无法在添加枚举类的时候,就为属性interfaceType赋值;

  这就很尴尬,不过好在有注解@PostConstruct,被该注解声明的方法,会在注解@Resource或@Autowired执行后,再执行;

  这样一来,我们就可以在PostContruct()方法中拿到注入的bean对象,进而就可以为指定的枚举类重新为其属性interfaceType进行赋值;

  这样,就实现了:为不同的接口注入不同的业务实现类,也就是不同接口可以自动调用各自的业务处理类。

  但是,在实际测试中发现,注入的bean对象还是为空。

3.解决方案

 // @Setter不支持直接声明在枚举类上
@Getter
@AllArgsConstructor
public enum CzInterfaceEnum {
    // 下面有枚举类的构造方法
    INTERFACE_CZ5101( "cz5101" );

    @JsonValue
    private String interfaceName;

    // 接口类型
    @Setter
    private InterfaceCz interfaceType;

    /**
     * 为枚举类注入spring管理的bean对象
     * @description:
     * @attention: 对象的注入必须创建一个单独的类来完成,不然注入的对象都是null
     * @author: Marydon
     * @date: 2020年10月29日 0029 17:47
     * @version: 1.0
     * @email: marydon20170307@163.com
     */
    @Component
    public static class EnumTypeServiceInjector {
        // 为该类注入对象
        @Resource private InterfaceCz cz5101Impl;
        /*
         * 将注入的对象添加到对应的枚举类中
         * @attention:
         * @date: 2020年11月13日 0013 19:02
         * @param:
         * @return: void
         */
        // @Autowired, @Resource执行后会走该注解
        @PostConstruct
        private void postConstruct() {
            INTERFACE_CZ5101.setInterfaceType(cz5101Impl);
        }
    }

    /*
     * 创建只有一个参数的构造方法
     * @explain: 创建枚举类(只给一个属性赋值)
     * 另一个属性通过EnumTypeServiceInjector注入对象并赋值
     * @attention:
     * @date: 2020年11月13日19:13:01
     * @param: interfaceName 接口名称
     * @return:
     */
    CzInterfaceEnum(String interfaceName) {
        this .interfaceName = interfaceName;
    }
}

  这样,当我们使用枚举的时候,就能获得它所注入的对象。

  说明:

  通过@Autowire或@Resource注入的对象,支持开启多线程异步访问

  使用场景,见文末推荐。

posted @ 2021-01-22 10:16  Marydon  阅读(4938)  评论(0编辑  收藏  举报