Новости
15.11.2017

Spring: Инверсия управления(внедрение зависимостей) - IoC/DI


"конспект" еще в процессе

Спросили знаю ли я Spring - конечно не знаю, но могу научиться из книжек. Вот и стал читать книжку, начинается все с Dependency Injection - но как-то непонятно написано, сделаю ка я конспэкт, что-бы потом по новой не расшифровывать о чем там писал автор.

Для регистрации компонента необходимо в конфигурационном файле указать класс бина с соответствующим идентификатором.
<bean id="fooAction1" class="ru.gootsite.stud.spring.FooAction1" />

Можно заставить контейнер сканировать пакет на предмет анатированных классов, тогда вместо настройки через файл конфигурации можно регистрировать управляемые объекты по средствам размещения аннотаций перед классами.
Аннотации для регистрации находятся в пакете org.springframework.stereotype:

Аннотации бинов
@Controller  
@Repository  
@Service
@Component
Бины предоставляющие логику либо данные

<context:component-scan base-package="ru.gootsite"></context:component-scan>

@Service("fooAction1")
public class FooAction1 implements FooAction {...

Dependency Pull
По всей видемости этот тип подразумевает получение зависимости через метод контекста getBean(<id>,<Object.class>).

ApplicationContext ctx = new ClassPathXmlApplicationContext("app-context.xml");
InjObj mp = ctx.getBean("exampleObj", InjObj.class);

Contextualized Dependency Lookup
Управляемый компонент реализует некоторый интерфейс в котором есть метод принимающий в качестве параметра контейнер. Собственно зависимости извлекаются за счет манипуляций с объектом контейнера.

Constructor Dependency Injection
В этом случае зависимости внедряются в параметры конструктора объекта.
Для настройки этого типа зависимостей используется пространство с.

<bean id="messageProvider" class="ru.gootsite.ConfMessageProvider" c:message="Строка для конструктора" >
 <!-- еще можно с помощью дескриптора constructor-arg -->
 <constructor-arg type="int">
 <value>100500</value>
 </constructor-arg>
</bean>

public class ConfMessageProvider implements MessageProvider {
 public ConfMessageProvider(String message) {
  this.message = message;...

также возможно использование аннатаций

@Service("objConsDeps")
public class ObjConsDeps {
 private ObjMessage message;
 @Autowired
 public ObjConsDeps(ObjMessage objMessage1) {
  this.message = objMessage1;
}

@Service("objMessage")
public class ObjMessage {
 public void sayWord() {
  System.out.println("word");
 }
}

Еще можно внедрять значения прямо в параметры конструктора, но мне не хочется показывать как перед параметром ставится аннатация, которая фактически задает значение по умолчанию, пока не найду что-то приличней.

Setter Dependency Injection
Самый адекватный и простой в использовании тип внедрения зависимости.

xml
 <bean id="messageRenderer" class="ru.gootsite.StandardOutMessageRender">
 <property name="messageProvider" ref="messageProvider"></property>
</bean>
<bean id="messageProvider" class="ru.gootsite.HelloWorldMessageProvider"></bean>
аннотации
@Service("messageRenderer")
public class StandardOutMessageRender implements MessageRenderer {
 private MessageProvider messageProvider;
 
 @Autowired
 public void setMessageProvider(MessageProvider provider) {
  this.messageProvider = provider;...

@Service("messageProvider")
 public class HelloWorldMessageProvider implements MessageProvider {...

Также есть какие-то пространства p в ядре и из можно использовать для зависимостей в свойствах, но мне так показалось, что это "вода"... для книжки, если столкнусь с этим дальше, то напишу.

Lookup Method Injection (внедрение через метод)
Когда дошел до этого параграфа стало безумно интересно - неужели можно "подкинуть" методы внедряемого объекта в зависимы, а вот и нет - оказалось, что это просто реализация метода получения зависимости контейнером. Реализуемый метод возвращает объект, который можно использовать потом... как стратегию например.

<bean id="fooAction1" class="ru.gootsite.stud.spring.FooAction1" scope="prototype" />
<bean id="fooAction2" class="ru.gootsite.stud.spring.FooAction2" scope="prototype" />
<bean id="fooActions" class="ru.gootsite.stud.spring.AbstractFooBarActions">
 <lookup-method name="getPrintWord" bean="fooAction2" />
</bean>

public interface FooBarActions {
 public void printWord();
}

public abstract class AbstractFooBarActions implements FooBarActions {
 public abstract FooAction getPrintWord();
 public void printWord() {
  this.getPrintWord().printWord();
 }
}

public interface FooAction {
 public void printWord();
}

public class FooAction1 implements FooAction {
 public void printWord() {
  System.out.println("word1");
 }
}