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

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

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

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

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

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

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) объект.

Другие вопросы по тегам