使用spring注释将对象注入到singleton类中

时间:2016-11-09 21:16:33

标签: java spring dependency-injection

如何使用spring注释将对象注入到singleton类中?

我有一些代码,如下面的代码片段,我想将B类对象注入其中。

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();
    services.AddAuthentication();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseOAuthValidation();

    app.UseOpenIdConnectServer(options =>
        {
              //..... Copy-paste from the OpenIdConnect page

              OnValidateTokenRequest = context => { ... }
              OnHandleTokenRequest = context => { ... }
        });

    app.UseMvc();
}

当我在b对象上面使用@Inject时,我有NullPointerException。

public class A {
    private B b;
    private static A instance;

    private A () {
        set some timer tasks
        ...
    }

    public A getInstance() {
        if (instance == null) { instance = new A(); }
        return instance;
    }

3 个答案:

答案 0 :(得分:2)

在Spring应用程序中,您不需要不应该创建单例类。当您创建单例bean时,Spring将确保在上下文中只存在此类的单个实例(singleton是默认的bean范围)。

你的课应该是这样的:

@Component
public class SessionHolder {

    private PdbIdContainer pdbIdContainer;

    private Map<UUID, SessionData> sessionMap;

    @Autowired // you can omit @Autowired if you use Spring 4.3 or higher
    SessionHolder(PdbIdContainer pdbIdContainer) {
        this.pdbIdContainer = pdbIdContainer;
        this.sessionMap = new ConcurrentHashMap<>();
        pdbIdContainer.update();
        TimerTask timerTask1 = new TimerTask() {
            @Override
            public void run() {
                Date d = new Date();
                sessionMap.entrySet().stream().filter(map -> TimeUnit.MILLISECONDS.toMinutes(
                        d.getTime() - map.getValue().getLastUseTime().getTime()) >= Integer.parseInt(
                        AppController.getConfig().getSessionInterval())).forEach(map -> sessionMap.remove(map.getKey()));
            }
        };
        TimerTask timerTask2 = new TimerTask() {
            @Override
            public void run() {
                pdbIdContainer.update();
            }
        };
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(timerTask1,
                                  Integer.parseInt(AppController.getConfig().getSessionMapDelay()),
                                  Integer.parseInt(AppController.getConfig().getSessionMapInterval()));
        timer.scheduleAtFixedRate(timerTask2,
                                  Integer.parseInt(AppController.getConfig().getPdbIdsSetDelay()),
                                  Integer.parseInt(AppController.getConfig().getPdbIdsSetInterval()));
    }

    public SessionData getSession(UUID id) {
        return sessionMap.get(id);
    }

    public UUID createSession(StructureContainer structure) {
        UUID id = UUID.randomUUID();
        sessionMap.put(id, new SessionData(structure, new Date()));
        return id;
    }
}

答案 1 :(得分:1)

我建议使用CDI注释(@Inject中的javax.inject.Inject),而不是Spring的@Autowired,如果可行的话。这样,如果您需要将另一个DI提供商转移到另一个public class A { @Inject //or @Autowired - Spring private B b; private static A instance; 提供商,那么您就不会受到Spring的束缚。

for (int i=1; i<= sheet.getLastRowNum(); i++){
        String keyword = sheet.getRow(i).getCell(0).getStringCellValue();
        searchBox.clear();
        searchBox.sendKeys(keyword);
        searchBox.submit();
        driver.manage().timeouts().implicitlyWait(8, TimeUnit.SECONDS);
    }

答案 2 :(得分:1)

如果没有管理对象的生命周期,我认为Spring不会开箱即用。

启用此功能的唯一方法是打开编译时或加载时间aspectj编织。

您可以完全跳过注入,并抓取应用程序上下文的实例并从中检索B实例。

更多详情:Dependency Injection into Spring non-managed beans