CDI延期注射不起作用

时间:2014-02-08 00:07:39

标签: java dependency-injection cdi

我在下一个场景中遇到CDI的问题:

Initializator注入ServletContextListener。但是在一些其他“步骤”之后,调用方法启动:

@WebListener
public class ContextListener implements ServletContextListener {

   @Inject
   private Initializator initializator;

   public void contextInitialized(ServletContextEvent event) {
         ServletContext servletContext = (ServletContext) event.getSource();
         String contextPath = ((ServletContext) event.getSource()).getContextPath();
         String serverName = servletContext.getInitParameter("SERVER_NAME");
         initializator.startup(serverName);
         System.out.println("ServletContext " + contextPath + " stated.");
   }

   public void contextDestroyed(ServletContextEvent event) {
         String contextPath = ((ServletContext) event.getSource()).getContextPath();
         System.out.println("ServletContext " + contextPath + " stopped.");
   }

}

存储库成功注入初始化器:

public class Initializator {

   @Inject
   private ChannelRepository repo;

   public String serverName;

   public void startup(String aServerName) {
         this.serverName = aServerName;
         initAll();
   }

   private void initAll() {
         List<Channel> channels = repo.getChannels();
         for (Channel channel : channels) {
                channel.start();
         }
   }

}

存储库检索数据并实例化通道:

public class ChannelRepository {

   public List<Channel> getChannels() {
         List<Channel> channels = new ArrayList<Channel>();
         // ...some db access via jdbc (or jpa)
         channels.add(new Channel("dummy", 8080));
         return channels;
   }
}

频道需要记录器:

public class Channel extends Thread {

   @Inject
   private Logger logger;

   public String name;
   public int port;

   public Channel(String aName, int aPort) {
         this.name = aName;
         this.port = aPort;
   }

   @Override
   public void run() {
         logger.log("Channel " + name + " is running in port " + port);
         // ...some other things to do
   }
}

如何避免手动创建频道实例?

问题已经完成,因为在实例构建之后调用了Initializator中的启动方法。

如何管理此类“延期”注射?

1 个答案:

答案 0 :(得分:0)

避免使用

手动创建Channel实例
new Channel()

相当容易。

首先,我们需要Channel类中的默认构造函数和channel属性的setter。

然后您必须将此添加到您的频道回购

@Inject
Instances<Channel> channelInstances;

并在您的repo方法中更改

channels.add(new Channel("dummy", 8080));

Channel channel = channelInstances.get();
channel.setPort(8080);
channel.setName("dummy");
channels.add(channel);

一个小提示: 如果可以,请不要让Channel扩展Thread,而是执行以下操作

final Channel channel = channelInstances.get();
channel.setPort(8080);
channel.setName("dummy");

channels.add(new Thread() {
  @Override
  public void run() {
    channel.doTheChannelStuff();
    channelInstances.destroy(channel);
  }
}

为什么要这样做:

在某些情况下,当您尝试使用它时,会引入内存泄漏。 (工作中有类似的问题)这与依赖范围(默认)依赖关系和“手动”创建新实例有关。