JAVA

индекс
157,35

Spring IoC Annotation-based configuration, часть 2

В предыдущей статье я рассказал об основных аннотациях Spring IoC, однако есть еще несколько интересных вещей, о которых хотелось бы поведать.
Для, тех, кто не в курсе, что такое Spring Framework предлагаю почитать вот эту статью.



Еще несколько слов об @Autowired


Аннотация @Autowired может применяться не только к полям бина чтобы заинъектить в них зависимости, но так же к сеттерам, конструкторам и методам. Рассмотрим, что же будет значить @Autowired в каждом из этих случаев.

1. @Autowired примененный к сеттеру
Пусть наш подопытный бин, который мы будет инъектить выглядит так:
package ru.mypackage;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service("testBean")
@Scope("singleton")
public class TestBean {
  private String data = "I am a singleton!!";
  
  public String getData() {
    return data;
  }

  public void setData(String data) {
    this.data = data;
  }
}


* This source code was highlighted with Source Code Highlighter.

А бин, в который будем инъектить такой:
package ru.mypackage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service("lab1Bean")
@Scope("session")
public class SimpleBean {

  private TestBean bean;

  @PostConstruct
  public void init() {
    System.out.println(bean.getData());
  }

  public void setBean(TestBean bean) {
    this.bean = bean;
  }
}


* This source code was highlighted with Source Code Highlighter.

Собственно в таком случае, если мы поставим @Autowired перед сеттером setBean:
@Autowired
public void setBean(TestBean bean) {
  this.bean = bean;
}


* This source code was highlighted with Source Code Highlighter.

он заинъектит в поле бина синглтон TestBean'a и в консоли мы увидим заветное «I am a singleton!!».

2. @Autowired примененный к конструктору
Ситуация аналогичная — если мы добавим вот такой конструктор:
@Autowired
public SimpleBean (TestBean bean) {
  this.bean = bean;
}


* This source code was highlighted with Source Code Highlighter.

то в консоли увидим долгожданное «I am a singleton!!».

3. @Autowired примененный к методу
Самая интересная ситуация, добавляем вот такой метод
@Autowired
public void doSomething(TestBean bean) {
  this.bean = bean;
  System.out.println("I'm an autowired method and " + bean.getData());
}


* This source code was highlighted with Source Code Highlighter.

Spring автоматически вызовет doSomething и передаст ему экземпляр TestBean. В консоли появится:
I'm an autowired method and I am a singleton!!!
I am a singleton!!!
Первое напечатает doSomething, второе — init.
Обратите внимание, что необходимо устанавливать значение поля бина, Spring за вас этого не сделает. То есть если не писать this.bean = bean;, то в методе init будет NullPointerException.
Еще у @Autowired есть необязательное свойство required. При required=false Spring не будет кидать исключение, если не найдет в контексте необходимого бина. То есть вот такой класс вполне нормально создастся:
package ru.mypackage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service("lab1Bean")
@Scope("session")
public class SimpleBean {

  @Autowired(required=false)
  private TestBean bean;

  @PostConstruct
  public void init() {
//    System.out.println(bean.getData());
  }

  public void setBean(TestBean bean) {
    this.bean = bean;
  }
}


* This source code was highlighted with Source Code Highlighter.

Аннотация @Qualifier


Данная аннотация позволяет несколько специфицировать бин, который необходим для @Autowired. @Qualifier принимает один входной параметр — имя бина.
@Autowired
@Qualifier("specialTestBean")
private TestBean bean;


* This source code was highlighted with Source Code Highlighter.

Эта конструкция будет искать в контексте бин с именем specialTestBean и в нашем примере мы соответственно получим исключение, так как TestBean объявлен с именем 'testBean' (@Service(«testBean»)).
На основе @Qualifier можно создавать свои признаки бинов, об этом достаточно хорошо написано (и, что немаловажно, с огромным количеством примеров) в Spring Reference Manual.

Аннотация @Resource


@Resource — аннотация Java EE 5 и Java 6. По действию аналогична @Autowired. В качестве параметра 'name' может принимать имя бина. Примеры выше можно переписать вот так:
// @Autowired
// аналогично
@Resource
private TestBean bean;


* This source code was highlighted with Source Code Highlighter.

и
// @Autowired
// @Qualifier("specialTestBean")
@Resource(name="specialTestBean")
private TestBean bean;


* This source code was highlighted with Source Code Highlighter.


На этом про аннотации Spring IoC можно закончить. Надо подвести какие-то выводы...
Spring безусловно стал стройнее, красивее с приходом стиля конфигурирования аннотациями, однако, как показывает практика, механизм пока не отлажен, т.к. иногда случается, что Spring хоть убей не хочет принимать аннотированный бин, а описанный через XML легко проглатывает.
+4
8 января 2009, 22:14
18

комментарии (3)

0
sirus #
да, с приходом аннотаций программировать стало гораздо приятнее, много черновой работы убирается. Мне раньше не очень нравился Spring, но когда узнал как работают аннотации в версии 2.5 — любовь на веки.

Вот примерчик моего рабочего кода
  @RequestMapping(value = "/compset_analysis", params = {"action=hotel-etalons"})
public ModelAndView getApprovedMarket(@RequestParam(required = false) String market, @Qualifier HotelEtalonsCompSetAnalysisView etalonsView){
...
}


* This source code was highlighted with Source Code Highlighter.


обратите внимание как передается параметр @Qualifier HotelEtalonsCompSetAnalysisView etalonsView

автору, спасибо.
идем дальше? сможете осветить тему про Lazy, @Transaction, OpenSessionInViewInterceptor, OpenSessionInViewFilter

0
MaEcTPo #
А вы можете осветить тему про OpenSessionInViewInterceptor, OpenSessionInViewFilter?
Думаю, что пока вы напишете — я найду решение свой проблемы, но потом другим людям полезно будет.

Спасибо.
0
sedovmik #
Я думаю здорово было бы отметить как работает @Autowired для множества бинов.
Если есть некий интерфейс A и несколько бинов, реализующих этот интерфейс заавтовайрить можно их всех:

@Autowired
private Set<A> aSet;

btw, автовайринг одного бина по типу A приведёт к исключению.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.