我在下一个场景中遇到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中的启动方法。
如何管理此类“延期”注射?
答案 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);
}
}
为什么要这样做:
在某些情况下,当您尝试使用它时,会引入内存泄漏。 (工作中有类似的问题)这与依赖范围(默认)依赖关系和“手动”创建新实例有关。