Nowhere in the CDI spec it is said that bean instances retrieved from Instance.get() and from iterating with Instance.iterator() should be treated differently regarding their destruction. In other words, it's normal that Instance.get() and Instance.iterator().next() behave the same. So your trick is exploiting a bug in Weld 1.1 Weld 2.3 is behaving correctly according to CDI 1.2 spec. You're using Instance to request instances for dependent beans. Section 6.4.2 of the spec reads:
Dependent objects of a contextual instance are destroyed when Contextual.destroy() calls CreationalContext.release(), as defined in The CreationalContext interface.
Additionally, the container must ensure that:
- all dependent objects of a non-contextual instance of a bean or other Java EE component class are destroyed when the instance is destroyed by the container,
We are in this case. The CDI container doesn't guarantee that all instances will be destroyed with the destruction of injecting servlet. So don't expect it to happen during your servlet life. You have to use Instance.destroy() method to explicitly cleanup your dependent instances. Now, why don't you experience memory leak when CDIBean2 is injected directly and not thru Instance<CDIBean2>? Probably because Weld use an optimisation allowed by the spec (end of section 6.4.2):
Finally, the container is permitted to destroy any @Dependent scoped contextual instance at any time if the instance is no longer referenced by the application (excluding weak, soft and phantom references).
But as you see it's not guarantee: Weld is doing you a favour here. So to comply CDI code, your example should be ;edified like this:
@WebServlet("/Servlet") |
public class Servlet extends HttpServlet { |
private static final long serialVersionUID = 1L; |
|
@Inject |
private Instance<CDIInterface> cdi; |
/** |
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response) |
*/ |
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
CDIInterface myInterface = cdi.get(); |
response.getWriter().write("Here " + Servlet.class.getName() + " - " + myInterface.sayHello()); |
cdi.destroy(myInterface); |
} |
|
} |
|
public interface CDIInterface { |
|
public abstract String sayHello(); |
} |
|
@Default |
public class CDIBean implements CDIInterface{ |
|
@Inject |
private Instance<CDIBean2> bean2; |
|
public String sayHello() { |
CDIBean2 myBean2 = bean2.get(); |
return "Here " + CDIBean.class.getName() + " - " + myBean2.get().testHello(); |
bean2.destroy(myBean2); |
} |
|
} |
|
public class CDIBean2 { |
|
public String testHello() { |
return "Here " + CDIBean2.class.getName(); |
} |
}
|
|