1

すべてのコンポーネントをキャッシュする PicoContainer があります。すべてのコンポーネントをキャッシュするため、コンテナーのライフサイクルの適切な時点で、startstop呼び出すことを期待しています。dispose

ただし、を使用してコンポーネントを構築するFactoryInjectorと、そのコンポーネントもキャッシュされているにもかかわらず、これらのメソッドがまったく呼び出されないことがわかりました。

次の例を見てください。

import java.lang.reflect.Type;

import org.picocontainer.Characteristics;
import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.Disposable;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoContainer;
import org.picocontainer.Startable;
import org.picocontainer.injectors.FactoryInjector;

public class PicoContainerFactoryTest {
    public static void main(String[] args) {
        MutablePicoContainer container =
            new DefaultPicoContainer().as(Characteristics.CACHE);
        try {
            System.out.println("Adding components...");
            container.addComponent(InstanceService.class,
                                   new InstanceServiceImpl());
            container.addComponent(ConstructedService.class,
                                   ConstructedServiceImpl.class);
            container.addAdapter(
                new FactoryConstructedServiceAdapter());

            System.out.println("Starting...");
            container.start();

            // Even this doesn't trigger it. :(
            //container.getComponent(FactoryConstructedService.class);

            System.out.println("Stopping...");
            container.stop();
        }
        finally
        {
            System.out.println("Disposing...");
            container.dispose();
        }
    }


    public interface InstanceService
        extends Startable, Disposable {}
    public interface ConstructedService
        extends Startable, Disposable {}
    public interface FactoryConstructedService
        extends Startable, Disposable {}

    private static class InstanceServiceImpl extends Impl
            implements InstanceService {
        public InstanceServiceImpl() {
            super("InstanceServiceImpl");
        }
    }

    public static class ConstructedServiceImpl extends Impl
            implements ConstructedService {
        public ConstructedServiceImpl() {
            super("ConstructedServiceImpl");
        }
    }

    private static class FactoryConstructedServiceAdapter
            extends FactoryInjector<FactoryConstructedService> {

        public FactoryConstructedServiceAdapter() {
            super(FactoryConstructedService.class);
        }

        @Override
        public FactoryConstructedService getComponentInstance(
            PicoContainer picoContainer, Type type) {
            return new FactoryConstructedServiceImpl();
        }

        private static class FactoryConstructedServiceImpl extends Impl
            implements FactoryConstructedService {
            public FactoryConstructedServiceImpl() {
                super("FactoryConstructedServiceImpl");
            }
        }
    }

    public static class Impl implements Startable, Disposable {
        private final String name;

        public Impl(String name) {
            this.name = name;
            System.out.println("  " + name + "#<init>");
        }

        @Override
        public void start() {
            System.out.println("  " + name + "#start");
        }

        @Override
        public void stop() {
            System.out.println("  " + name + "#stop");
        }

        @Override
        public void dispose() {
            System.out.println("  " + name + "#dispose");
        }
    }
}

これを実行した結果は次のようになります。

Adding components...
  InstanceServiceImpl#<init>
Starting...
  ConstructedServiceImpl#<init>
  InstanceServiceImpl#start
  ConstructedServiceImpl#start
Stopping...
  ConstructedServiceImpl#stop
  InstanceServiceImpl#stop
Disposing...
  ConstructedServiceImpl#dispose
  InstanceServiceImpl#dispose

というわけでstart()、作成してインスタンスとして注入したコンポーネントが起動します。コンストラクター注入によって注入したコンポーネントが構築され、開始されます。しかし、工場経由で注入したコンポーネントからは何も見えません。

ドキュメントに関する限り、Javadoc for show FactoryInjector#startおよび#stopmethods#disposeは、ファクトリがスピンアウトするコンポーネントではなく、ファクトリ自体が独自のライフサイクル処理を実行することを目的としているようです。

ソースをざっと見てみると、アダプターの実装でComponentLifecycleメソッドが呼び出されることがわかりますが、それをフックする方法がすぐにはわかりません。他の実装クラスを見ると、実際にはすべてが別のものに委譲されているようです。実際に何が起こっているのかを理解するのは困難です。

これを行う適切な方法は何ですか?これを行う適切な方法はありますか?

4

1 に答える 1

2

FactoryConstructedServiceAdapter は LifecycleStrategy を実装し、

@Override
public boolean hasLifecycle(Class<?> type) {
    return true;
}

基本的にこれですべてです。ファクトリは標準のライフサイクルに含まれ、コンポーネントを管理できます。また、FactoryConstructedServiceImpl の実際のインスタンス化が呼び出されます (ファクトリによって提供されるコンポーネントにライフサイクルが必要なく、なぜインスタンス化されないのか疑問に思う場合は、ファクトリは怠惰であり、実際にコンポーネントを接続または要求するまでログに「FactoryConstructedServiceImpl#init」が表示されないことに注意してください)。

大きな例が必要な場合は、InstanceAdapter を使用してください。

于 2015-06-02T14:56:33.697 に答える