Spring 中如何通过 Autowired 往 Java 枚举中注入 Service 依赖?

假设我们的 Spring Boot 有一个 Service 类:

package com.awaimai.service;
import org.springframework.stereotype.Service;

@Service
public class PostService {
    public void print(String text) {
        System.out.println(text);
    }
}

以及一个Lang枚举类,它会引用 PostService 里面的 print 方法,如下:

package com.awaimai.enumeration;
import org.springframework.beans.factory.annotation.Autowired;

public enum Lang {
    CHINESE("这是中文"),
    ENGLISH("This is English"),
    ARABIC("هذا عربي");

    private final String text;
    @Autowired
    private PostService postService;

    Lang(String text) {
        this.text = text;
    }

    public void printText() {
        postService.print(text);
    }
}

这样写运行的时候会报NullPointerException错误,因为 @Autowired 只能用在有效 Spring Bean 里面,包括BeanServiceComponent等,而 enum 却不是 Bean,所以 Service 对象不会自动注入进来。

解决办法就是:增加一个内部类,让它在 Spring Boot 启动的时候就往枚举中注入

package com.awaimai.enumeration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.EnumSet;

public enum Lang {
    CHINESE("这是中文"),
    ENGLISH("This is English"),
    ARABIC("هذا عربي");

    private final String text;
    private PostService postService;

    Lang(String text) {
        this.text = text;
    }

    public void printText() {
        postService.print(text);
    }

    public void setPostService(PostService postService) {
        this.postService = postService;
    }

    @Component
    public static class SetPostService {
        // 因为这个类是个 Component,所以 Spring Boot 启动的时候会自动注入依赖
        @Autowired
        private PostService postService;

        @PostConstruct
        public void setPostService() {
            for (Lang lang: EnumSet.allOf(Lang.class)) {
                lang.setPostService(postService);
            }
        }
    }
}

下面是测试代码:

package com.awaimai.enumeration;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import static com.awaimai.enumeration.Lang.*;

@SpringBootTest
class LangTest {
    @Test
    void printText() {
        CHINESE.printText();
        ENGLISH.printText();
        ARABIC.printText();
    }
}

打印结果:

这是中文
This is English
هذا عربي

参考资料:

  1. Inject bean into enum

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

昵称 *