Is it possible to destroy a CDI scope?

2020-08-26 03:59发布

I'm working on a Java EE application, primarily JAX-RS with a JSF admin console, that uses CDI/Weld for dependency injection with javax.enterprise.context.ApplicationScoped objects. Minor debugging issues aside, CDI has worked beautifully for this project.

Now I need some very coarse-grained control over CDI-injected object lifecycles. I need the ability to:

  • Remove an injected object from the application context, or
  • Destroy/delete/clear/reset/remove the entire application context, or
  • Define my own @ScopeType and implementing Context in which I could provide methods to perform one of the two above tasks.

I'm fully aware that this is across, if not against, the grain of CDI and dependency injection in general. I just want to know

  • Is this remotely possible?
  • If yes, what is the easiest/simplest/quickest/foolproofiest way to get the job done?

4条回答
女痞
2楼-- · 2020-08-26 04:34

In CDI 1.1 there is a javax.enterprise.context.spi.AlterableContext interface, which allows you to individually destroy a bean instance. All normal scopes (request, conversation, session) are alterable.

AlterableContext ctxConversation = (AlterableContext) beanManager.getContext(ConversationScoped.class);
for (Bean<?> bean : beanManager.getBeans(Object.class)) {
    Object instance = ctxConversation.get(bean);
    if (instance != null) {
        ctxConversation.destroy(instance);
    }
}

The beanManager here is a javax.enterprise.inject.spi.BeanManager instance. You can get it via JNDI lookup:

InitialContext.doLookup("java:comp/BeanManager");

or via CDI static method:

CDI.current().getBeanManager();

, but be aware of the issues with the static method in some Weld versions:

查看更多
欢心
3楼-- · 2020-08-26 04:36

A custom scope which might fit your needs is available at https://github.com/openknowledge/openknowledge-cdi-extensions/tree/master/openknowledge-cdi-scope/src/main/java/de/openknowledge/cdi/scope Maybe you have to adjust the implementation a bit.

查看更多
Melony?
4楼-- · 2020-08-26 04:47

Weld Reference Documentation Section 2.1.2

Keep in mind that once a bean is bound to a context, it remains in that context until the context is destroyed. There is no way to manually remove a bean from a context. If you don't want the bean to sit in the session indefinitely, consider using another scope with a shorted lifespan, such as the request or conversation scope.

Custom scope example Porting the veiwscoped jsf annonation to cdi

If you really don't want to take the path of the Custom scope type.. You can use a non-portable method by using BeanManager.getContext method and cast this context in a weld AbstractSharedContext to have access to the beanstore or the cleanUp() method of the context.

Check this thread on how to get a BeanManager instance for your environment

查看更多
【Aperson】
5楼-- · 2020-08-26 04:49

Out of the box there is only the Conversation scope that gives you total control on its lifecycle. But you can create your own scope if conversation doesn't suit your needs. Creating a scope is a tough job, but you can go to weld code and look how conversation was implemented.

查看更多
登录 后发表回答