CDI 2.0,Java SE - weld-se-shaded 3.0 中未调用条件观测器方法。5.Final
CDI 2.0, Java SE - conditional observer method not called in weld-se-shaded 3.0.5.Final
我遇到了未调用的条件观察器方法的问题。这是代码,从 junit 测试开始:
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class CDIMinimalConditionalObserverTest
{
private final static Logger LOGGER = LogManager.getLogger(CDIMinimalConditionalObserverTest.class);
private SeContainer container;
@Before public void before()
{
LOGGER.debug("before");
final SeContainerInitializer initialiser = SeContainerInitializer.newInstance();
container = initialiser.initialize();
}
@After public void after()
{
container.close();
LOGGER.debug("after");
}
@Test public void testObservation_observationInManagedNonExistentConditionalObservers()
{
CDIMinimalConditionalObserverEvent event = new CDIMinimalConditionalObserverEvent();
container.getBeanManager().fireEvent(event);
assertThat(event.msg, nullValue());
}
@Test public void testObservation_observationInManagedExistentConditionalObservers()
{
// create observer by selection
Instance<CDIMinimalConditionalObserver> instance = container.select(CDIMinimalConditionalObserver.class);
CDIMinimalConditionalObserver observer = instance.get();
assertThat(observer, notNullValue());
CDIMinimalConditionalObserverEvent event = new CDIMinimalConditionalObserverEvent();
container.getBeanManager().fireEvent(event);
observer.doSomething();
assertThat(event.msg, notNullValue());
}
}
这里是class条件观察者方法:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.jmda.sandbox.cdi.se.CDIMinimalTests.SimpleInnerEvent;
/**
* {@link Model} annotation assigns non-dependent scope and thereby makes it possible to make {@link
* #observation(SimpleInnerEvent)} conditional
*/
@ApplicationScoped public class CDIMinimalConditionalObserver
{
private final static Logger LOGGER = LogManager.getLogger(SimpleConditionalObserver.class);
public CDIMinimalConditionalObserver()
{
LOGGER.debug("constructor");
}
@PostConstruct public void postConstruct()
{
LOGGER.debug("post construct");
}
@PreDestroy public void preDestroy()
{
LOGGER.debug("pre destroy");
}
public void observation(@Observes(notifyObserver=Reception.IF_EXISTS) CDIMinimalConditionalObserverEvent event)
{
event.msg = "observation";
LOGGER.debug(event.msg);
}
public void doSomething()
{
LOGGER.debug("doing something");
}
}
最后是活动 class:
public class CDIMinimalConditionalObserverEvent { String msg; }
测试失败,因为 event.msg 为 null,尽管它不应该为 null。日志输出不显示任何 "observation" 输出。如果删除条件,则测试通过。
有什么想法吗?谢谢!
当您的 @ApplicationScoped
Bean 被发现时,它不会立即实例化。
CDI
足够聪明,仅在需要时才初始化真实对象,即幕后对象。
您可以看到通过
检索一个 ApplicationScoped
Bean
final Instance<App> select = container.select(App.class);
final App app = select.get();
确实return一个代理实例。
在此阶段,仍然没有 App
Bean 附加到应用程序上下文。
现在,尝试与该对象交互(即使只是通过调用 toString
),并且 仅在 之后,触发事件。
您会注意到它确实有效,因为底层对象已通过其无参数构造函数实例化。
删除 Reception.IF_EXISTS
只是表示 CDI
它必须立即创建并附加到底层实例的上下文,以便它无论如何都可以接受传入的事件。
规范中记录了这种代理行为(我需要找到该页面),这就是 Bean 需要无参数构造函数的原因。
Dependent
范围 Bean 不会遇到这个问题,因为它们是在每次需要时从头开始创建的,并且不会被框架跟踪。对于单例、会话或请求范围的 Bean,需要代理才能正确管理它们。
Dependent
scope Bean,可以看到是一个"pure"实例
我遇到了未调用的条件观察器方法的问题。这是代码,从 junit 测试开始:
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class CDIMinimalConditionalObserverTest
{
private final static Logger LOGGER = LogManager.getLogger(CDIMinimalConditionalObserverTest.class);
private SeContainer container;
@Before public void before()
{
LOGGER.debug("before");
final SeContainerInitializer initialiser = SeContainerInitializer.newInstance();
container = initialiser.initialize();
}
@After public void after()
{
container.close();
LOGGER.debug("after");
}
@Test public void testObservation_observationInManagedNonExistentConditionalObservers()
{
CDIMinimalConditionalObserverEvent event = new CDIMinimalConditionalObserverEvent();
container.getBeanManager().fireEvent(event);
assertThat(event.msg, nullValue());
}
@Test public void testObservation_observationInManagedExistentConditionalObservers()
{
// create observer by selection
Instance<CDIMinimalConditionalObserver> instance = container.select(CDIMinimalConditionalObserver.class);
CDIMinimalConditionalObserver observer = instance.get();
assertThat(observer, notNullValue());
CDIMinimalConditionalObserverEvent event = new CDIMinimalConditionalObserverEvent();
container.getBeanManager().fireEvent(event);
observer.doSomething();
assertThat(event.msg, notNullValue());
}
}
这里是class条件观察者方法:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.jmda.sandbox.cdi.se.CDIMinimalTests.SimpleInnerEvent;
/**
* {@link Model} annotation assigns non-dependent scope and thereby makes it possible to make {@link
* #observation(SimpleInnerEvent)} conditional
*/
@ApplicationScoped public class CDIMinimalConditionalObserver
{
private final static Logger LOGGER = LogManager.getLogger(SimpleConditionalObserver.class);
public CDIMinimalConditionalObserver()
{
LOGGER.debug("constructor");
}
@PostConstruct public void postConstruct()
{
LOGGER.debug("post construct");
}
@PreDestroy public void preDestroy()
{
LOGGER.debug("pre destroy");
}
public void observation(@Observes(notifyObserver=Reception.IF_EXISTS) CDIMinimalConditionalObserverEvent event)
{
event.msg = "observation";
LOGGER.debug(event.msg);
}
public void doSomething()
{
LOGGER.debug("doing something");
}
}
最后是活动 class:
public class CDIMinimalConditionalObserverEvent { String msg; }
测试失败,因为 event.msg 为 null,尽管它不应该为 null。日志输出不显示任何 "observation" 输出。如果删除条件,则测试通过。
有什么想法吗?谢谢!
当您的 @ApplicationScoped
Bean 被发现时,它不会立即实例化。
CDI
足够聪明,仅在需要时才初始化真实对象,即幕后对象。
您可以看到通过
检索一个ApplicationScoped
Bean
final Instance<App> select = container.select(App.class);
final App app = select.get();
确实return一个代理实例。
在此阶段,仍然没有 App
Bean 附加到应用程序上下文。
现在,尝试与该对象交互(即使只是通过调用 toString
),并且 仅在 之后,触发事件。
您会注意到它确实有效,因为底层对象已通过其无参数构造函数实例化。
删除 Reception.IF_EXISTS
只是表示 CDI
它必须立即创建并附加到底层实例的上下文,以便它无论如何都可以接受传入的事件。
规范中记录了这种代理行为(我需要找到该页面),这就是 Bean 需要无参数构造函数的原因。
Dependent
范围 Bean 不会遇到这个问题,因为它们是在每次需要时从头开始创建的,并且不会被框架跟踪。对于单例、会话或请求范围的 Bean,需要代理才能正确管理它们。
Dependent
scope Bean,可以看到是一个"pure"实例