是否可以说,在下面的代码中,Hazelcast实例将是应用程序作用域?
@ApplicationScoped
public class Producer {
private HazelcastInstance instance;
@PostConstruct
public void afterCreate() {
instance = Hazelcast.newHazelcastInstance();
}
@Produces
public HazelcastInstance getInstance() {
return instance;
}
}
修改
此解决方案:
@ApplicationScoped
public class Producer {
private HazelcastInstance instance;
private Producer() {}
@PostConstruct
public void afterCreate() {
instance = Hazelcast.newHazelcastInstance();
}
@PreDestroy
public void beforeDestroy() {
if(instance != null) {
instance.shutdown();
}
}
@Produces
@ApplicationScoped
public HazelcastInstance getInstance() {
return instance;
}
}
答案 0 :(得分:4)
你Producer
bean将是应用程序作用域,这很清楚。
但是, HazelnutInstance
bean将为@Dependent
。
因此,如果您在代码中的某处执行@Inject HazelnutInstance
,它将从CDI视点注入一个依赖实例。
但是你总是返回相同的实例,从不在你的制作人中创建新对象,所以理论上,你正在共享那个实例。
但是,请留意豆生命周期!当注入它们的bean被销毁时,将销毁@Dependent
个bean。所以现在假设它涉及到这样的破坏尝试 - Weld将尝试销毁你的依赖bean并将调用@PreDestroy
(在"经典" bean)或@Disposes
(在有生产者的bean上)方法就可以了。
因此,在您的情况下,如果某处disposer method处理HazelcastInstance
,可能会导致麻烦,因为每次Weld尝试销毁/处置该依赖bean时都会调用它
如果你使HazelcastInstance
应用程序作用域,你会更好。 E.g。
@Produces
@ApplicationScoped
public HazelcastInstance getInstance() {
return instance;
}
答案 1 :(得分:1)
我想通过单元测试来证明预期的行为。
代码和结果可以在下面找到。
<强> 环境 强>
UT使用arquillian
针对WebLogic 12.2.1远程容器启动<强> 1。 ApplicationScoped类和生成器,新实例:PASS
正如预期的那样,测试传递:生成的bean是应用程序作用域,因此注入相同的实例。
@ApplicationScoped
public class Producer {
private Producer() {}
@Produces
@ApplicationScoped
public HazelcastInstance getInstance() {
return Hazelcast.newHazelcastInstance();
}
}
<强> 2。 ApplicationScoped类和Dependent生成器,新实例:FAIL
正如预期的那样,测试失败:生成的bean为@Dependent
,注入了不同的实例。 (注意:@Dependent
是默认范围,它可以存在也可以不存在,相同的结果将是相同的。)
@ApplicationScoped
public class Producer {
private Producer() {}
@Produces
public HazelcastInstance getInstance() {
return Hazelcast.newHazelcastInstance();
}
}
第3。 ApplicationScoped类和Dependent生成器,post构造实例:PASS
正如预期的那样,测试通过:生成的instance
bean是@Dependent
。但是,它的生命周期间接绑定到Producer
生命周期(通过@PostConstruct
调用一次),因此,每次调用时返回相同的实例,并在生成器bean被销毁时取消引用。
注意 :在此实施中,Hazelcast未正常关闭。
@ApplicationScoped
public class Producer {
private HazelcastInstance instance;
private Producer() {}
@PostConstruct
public void afterCreate() {
instance = Hazelcast.newHazelcastInstance();
}
@Produces
public HazelcastInstance getInstance() {
return instance;
}
}
<强> 4。 ApplicationScoped类和ApplicationScoped生成器,post构造实例:PASS
正如预期的那样,测试传递:生成的bean为@ApplicationScoped
,并且在应用程序生命周期中返回相同的实例。
@ApplicationScoped
public class Producer {
private HazelcastInstance instance;
private Producer() {}
@PostConstruct
public void afterCreate() {
instance = Hazelcast.newHazelcastInstance();
}
@Produces
@ApplicationScoped
public HazelcastInstance getInstance() {
return instance;
}
}
<强> 5。依赖类和ApplicationScoped生成器,post构造实例:PASS
这个结果令人惊讶:Producer被注释为@Dependent
,它的生成器@ApplicationScoped
,结果是每个Producer实例都返回相同的实例。
原因:CDI使用作用域上下文
@Dependent
public class Producer {
private HazelcastInstance instance;
private Producer() {}
@PostConstruct
public void afterCreate() {
instance = Hazelcast.newHazelcastInstance();
}
@Produces
@ApplicationScoped
public HazelcastInstance getInstance() {
return instance;
}
}
<强> 6。依赖类和生成器,后构造实例:FAIL
正如预期的那样,测试失败:生成的bean为@Dependent
,注入了不同的实例。 (注意:@Dependent
是默认范围,它可以或不存在,相同的结果将是相同的)因为每个Producer实例将调用其自己的afterCreate
方法,导致不同的{{1}实例
instance
单元测试
@Dependent
public class Producer {
private HazelcastInstance instance;
private Producer() {}
@PostConstruct
public void afterCreate() {
instance = Hazelcast.newHazelcastInstance();
}
@Produces
public HazelcastInstance getInstance() {
return instance;
}
}
<强> arquillian.xml 强>
@RunWith(Arquillian.class)
public class ProducerTest {
@Deployment
public static WebArchive createDeployment() {
// Import Maven runtime dependencies
File[] files = Maven.resolver()
.loadPomFromFile("pom.xml")
.importRuntimeDependencies()
.resolve()
.withTransitivity()
.asFile();
// Create deploy file
WebArchive war = ShrinkWrap.create(WebArchive.class, ProducerTest.class.getName() + ".war")
.addClass(Producer.class)
.addClass(ProducerTest.class)
.addAsLibraries(files);
// Show the deploy structure
System.out.println(war.toString(true));
return war;
}
@Inject
private HazelcastInstance hzInstance1;
@Inject
private HazelcastInstance hzInstance2;
@Before
@After
public void cleanup() {
Hazelcast.shutdownAll();
assertEquals(emptySet(), getAllHazelcastInstances());
}
@Test
public void producerTest() {
assertTrue(hzInstance1.equals(hzInstance2));
}
}
<强> hazelcast.xml 强>
<?xml version="1.0"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://www.jboss.org/schema/arquillian/arquillian_1_0.xsd">
<container qualifier="wls-remote" default="true">
<configuration>
<property name="wlHome">PATH_TO_WLSERVER_DIRECTORY</property>
<property name="adminUrl">ADMIN_URL</property>
<property name="adminUserName">USER_NAME</property>
<property name="adminPassword">PASSWORD</property>
<property name="target">TARGET_SERVER</property>
</configuration>
</container>
</arquillian>
为了完整性,POM
<强>的pom.xml 强>
<?xml version="1.0" encoding="UTF-8"?>
<hazelcast
xsi:schemaLocation="http://www.hazelcast.com/schema/config
http://www.hazelcast.com/schema/config/hazelcast-config-3.5.xsd"
xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<group>
<name>producer</name>
<password>producer_pass</password>
</group>
<network>
<port auto-increment="false">10710</port>
<join>
<multicast enabled="false" />
<tcp-ip enabled="true">
<member>localhost</member>
</tcp-ip>
</join>
</network>
</hazelcast>
答案 2 :(得分:-2)
是的,制作人将收到您使用注释test class
应用的范围。这将导致整个CDI应用程序只有一个实例。对类<agm-map #gm [fitBounds]="latlngBounds" [zoom]="15">
<agm-marker *ngFor="let m of markers; let i = index"
[latitude]="m.geoCode.latitude"
[longitude]="m.geoCode.longitude"
(mouseOver)="onMouseOver(infoWindow,gm)"
>
<agm-info-window [disableAutoPan]="false" #infoWindow>
<div>
{{m.name}}
{{m.rating}}
</div>
<div>
<a (click)="onClickInfoView({id:m.id})" class="btn btn-attention pull-right">Daje <i class="fa fa-angle-double-right"></i></a>
</div>
</agm-info-window>
</agm-marker>
</agm-map>
onMouseOver(infoWindow, gm) {
if (gm.lastOpen != null) {
gm.lastOpen.close();
}
gm.lastOpen = infoWindow;
infoWindow.open();
}
的每个请求都将来到该类的同一个实例,因为它只会被初始化一次然后保持活动状态。由于Producer是应用程序范围的,@ApplicationScoped
的实例不会改变,只要你不在类本身中更改它(例如setter)
在应用程序的持续时间内,将创建一个定义为@ApplicationScoped的对象。
取自here