Comment créer et détruire CDI (Soudure) Haricots contrôlés via le BeanManager?

Je suis en train de créer des instances de CDI géré les haricots à l'aide de la BeanManager plutôt que de l'Instance .sélectionnez().get().

Cela a été suggéré qu'une solution à un problème que j'ai eu avec ApplicationScoped fèves de collecte des déchets et de leurs personnes à charge - voir CDI Application et Dépendante étendues peuvent se conjuguent pour expliquer l'impact de la collecte des ordures? pour le fond et cette solution de contournement proposée.

Si vous utilisez l'Instance programmatique méthode de recherche sur un ApplicationScoped bean, l'Instance de l'objet et de toute les haricots que vous obtenez à partir il sont tous en fin de compte dépend de la ApplicationScoped bean, et donc de partager son cycle de vie. Si vous créez des haricots avec le BeanManager, cependant, vous avez une poignée sur le Haricot instance elle-même, et peut apparemment explicitement le détruire, que je comprends, cela signifie qu'il sera GCed.

Ma démarche actuelle est de créer de la fève à l'intérieur d'un BeanManagerUtil classe, et retourner un objet composite de Haricot, de l'instance, et CreationalContext:

public class BeanManagerUtil {

    @Inject private BeanManager beanManager;

    @SuppressWarnings("unchecked")
    public <T> DestructibleBeanInstance<T> getDestructibleBeanInstance(final Class<T> type,
            final Annotation... qualifiers) {

        DestructibleBeanInstance<T> result = null;
        Bean<T> bean = (Bean<T>) beanManager.resolve(beanManager.getBeans(type, qualifiers));
        if (bean != null) {
            CreationalContext<T> creationalContext = beanManager.createCreationalContext(bean);
            if (creationalContext != null) {
                T instance = bean.create(creationalContext);
                result = new DestructibleBeanInstance<T>(instance, bean, creationalContext);
            }
        }
        return result;
    }
}

public class DestructibleBeanInstance<T> {

    private T instance;
    private Bean<T> bean;
    private CreationalContext<T> context;

    public DestructibleBeanInstance(T instance, Bean<T> bean, CreationalContext<T> context) {
        this.instance = instance;
        this.bean = bean;
        this.context = context;
    }

    public T getInstance() {
        return instance;
    }    

    public void destroy() {
        bean.destroy(instance, context);
    }
}

À partir de cela, dans le code appelant, alors je peux obtenir de l'instance elle-même, le mettre dans une carte pour une récupération ultérieure, et de l'utiliser comme d'habitude:

private Map<Worker, DestructibleBeanInstance<Worker>> beansByTheirWorkers =
    new HashMap<Worker, DestructibleBeanInstance<Worker>>();
...
DestructibleBeanInstance<Worker> destructible =
        beanUtils.getDestructibleBeanInstance(Worker.class, workerBindingQualifier);
Worker worker = destructible.getInstance();
...

Quand je suis fait avec elle, je peux rechercher le destructibles wrapper et l'appel destroy() sur celui-ci, et de la fève et de ses personnes à charge doit être nettoyé:

DestructibleBeanInstance<JamWorker> workerBean =
        beansByTheirWorkers.remove(worker);
workerBean.destroy();
worker = null;

Cependant, après l'exécution de plusieurs travailleurs et de laisser ma JBoss (7.1.0.Alpha1-SNAPSHOT) pendant 20 minutes ou donc, je peux voir GC survenant

2011.002: [GC
Desired survivor size 15794176 bytes, new threshold 1 (max 15)
1884205K->1568621K(3128704K), 0.0091281 secs]

Encore un JMAP histogramme affiche toujours le vieux travailleurs et de leurs dépendants des instances de traîner, unGCed. Ce qui me manque?

Par le débogage, je peux voir que le contexte le champ de la fève a créé le contexte de la bonne Travailleur, sans incompleteInstances et pas de parentDependentInstances. Il a un certain nombre de dependentInstances, qui sont comme prévu sur les champs du travailleur.

L'un de ces champs sur le Travailleur est en fait une Instance, et quand je compare ce champ avec celui d'un Travailleur récupéré via Instance par programme de recherche, ils ont un peu différent CreationalContext maquillage. Le champ d'Instance sur le Travailleur leva les yeux par Exemple, a le travailleur lui-même sous incompleteInstances, alors que le champ d'Instance sur le Travailleur (extrait de la BeanManager ne l'est pas. Elles ont toutes les deux identiques parentDependentInstances et dependentInstances.

Cela me fait penser que je n'ai pas le reflet de la récupération de l'instance correctement. Cela pourrait-il contribuer à l'absence de destruction?

Enfin, lors du débogage, je peux voir bean.destroy() appelée dans mon DestructibleBeanInstance.destroy(), et cela passe par de ManagedBean.détruire, et je peux voir les objets dépendants détruite dans le cadre de l' .release(). Cependant, ils ne pas obtenir ramasse miettes!

Toute aide sur ce serait très apprécié! Merci.

OriginalL'auteur Ben Kirby | 2011-12-07