Как зарегистрировать декорированные объекты в фреймворках Dependency Injection (PicoContainer)?

Я хочу обернуть ряд классов, реализующих интерфейс Job, объектом JobEnabledDecorator, который определяет, выполняется он или нет.

У меня возникли проблемы с выяснением того, как настроить это в PicoContainer, чтобы он знал, как создавать объекты реализации Job с оболочкой JobEnabledDecorator.

Возможно ли это в рамках внедрения зависимостей?

Возможно ли это в PicoContainer?

Если это так, любая помощь будет оценена.


person Alex Baranosky    schedule 18.12.2009    source источник


Ответы (1)


Возможно, вы захотите добавить «поведение». Короче говоря, вам нужно зарегистрировать фабрику поведения, которая создает поведение, обертывающее ваши адаптеры компонентов. Это легче описать на примере.

Во-первых, вы хотите создать контейнер, что-то вроде этого.

final MutablePicoContainer container = new PicoBuilder()
    .withBehaviors(new JobEnabledDecorating())
    .build();

Это означает, что после создания базового объекта — в вашем случае Job — вы хотите добавить к нему что-то дополнительное. Есть ряд встроенных поведений, но вам нужны собственные: JobEnabledDecorating.

public class JobEnabledDecorating extends AbstractBehaviorFactory {
    @Override
    public ComponentAdapter createComponentAdapter(
        final ComponentMonitor componentMonitor, final LifecycleStrategy lifecycleStrategy,
        final Properties componentProperties, final Object componentKey,
        final Class componentImplementation, final Parameter... parameters) throws PicoCompositionException 
    {
        return componentMonitor.newBehavior(
            new JobEnabledDecorated(
                super.createComponentAdapter(
                    componentMonitor, lifecycleStrategy, componentProperties, 
                    componentKey, componentImplementation, parameters
                )
            )
        );
    }
}

Фабрика создает JobEnabledDecorated поведения, обертывая адаптер компонента, который, в свою очередь, предоставляет ваши экземпляры. Настоящая работа теперь проделана в этом поведении.

public class JobEnabledDecorated extends AbstractBehavior<Job> {
    public JobEnabledDecorated(final ComponentAdapter<Job> delegate) {
        super(delegate);
    }

    @Override
    public Job getComponentInstance(final PicoContainer container, final Type into)
            throws PicoCompositionException {
        final Job instance = super.getComponentInstance(container, into);
        return new JobEnabledDecorator(instance);
    }

    @Override
    public String getDescriptor() {
        return "JobEnabledDecorator-";
    }
}

getComponentInstance запрашивает задание, добавляет декоратор и возвращает этот обернутый объект как новый экземпляр. Здесь вам придется добавить свою собственную логику.

public interface Job {
    void execute();
}

public class JobEnabledDecorator implements Job {
    private Job delegate;

    public JobEnabledDecorator(final Job delegate) {
        this.delegate = delegate;
    }

    @Override
    public void execute() {
        System.out.println("before");
        delegate.execute();
        System.out.println("after");
    }
}

public class MyJob implements Job {
    @Override
    public void execute() {
        System.out.println("execute");
    }
}

Вернемся к нашему использованию контейнера, рассмотрим этот пример.

    final MutablePicoContainer container = new PicoBuilder()
        .withBehaviors(new JobEnabledDecorating())
        .build();

    container.addComponent(Job.class, MyJob.class);

    final Job job = container.getComponent(Job.class);
    job.execute();

Запуск этого напечатает:

before
execute
after

Это, конечно, потому, что контейнер передал вам объект JobEnabledDecorator(MyJob).

person Ronald Blaschke    schedule 18.12.2009
comment
Спасибо за отличный ответ. К сожалению, я могу дать вам только один голос! - person Alex Baranosky; 19.12.2009
comment
Это полезно для вас, вот что важно. :-) - person Ronald Blaschke; 20.12.2009