Как работает автопроводка весной?


Я немного смущен тем, как инверсия управления (IoC) работает в Spring.

скажем у меня есть класс обслуживания под названием UserServiceImpl что реализует UserService интерфейс.

как это будет @Autowired?

и в моем Controllers, как бы instantiate an instance этой услугой?

Я бы просто сделать следующее?

UserService userService = new UserServiceImpl();
9 417

9 ответов:

во - первых, и самое главное - все весенние бобы управляются-они "живут" внутри контейнера, называемого "контекст приложения".

во-вторых, каждое приложение имеет точку входа в этом контексте. Веб-приложения имеют сервлет, JSF использует El-resolver, etc. Кроме того, есть место, где контекст приложения загружается и все бобовые - подгружен. В веб-приложениях это может быть прослушиватель запуска.

Autowiring происходит путем размещения экземпляр одного компонента в нужное поле в экземпляре другого компонента. Оба класса должны быть бобами, т. е. они должны быть определены, чтобы жить в контексте приложения.

что такое "жизнь" в контексте приложения? Это означает, что контекст создает экземпляры объектов, а не вы. То есть-ты никогда не сделаешь new UserServiceImpl() - контейнер находит каждую точку впрыска и устанавливает там экземпляр.

в ваших контроллерах, у вас просто есть следующее:

@Controller // Defines that this class is a spring bean
@RequestMapping("/users")
public class SomeController {

    // Tells the application context to inject an instance of UserService here
    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public void login(@RequestParam("username") String username,
           @RequestParam("password") String password) {

        // The UserServiceImpl is already injected and you can use it
        userService.login(username, password);

    }
}

несколько замечаний:

  • в своем applicationContext.xml вы должны включить <context:component-scan> Так что классы проверяются на @Controller,@Service и т. д. комментарии.
  • точкой входа для приложения Spring-MVC является DispatcherServlet, но он скрыт от вас, и, следовательно, прямое взаимодействие и загрузка контекста приложения происходит за сценой.
  • UserServiceImpl также должен быть определен как bean-либо с помощью <bean id=".." class=".."> или с помощью @Service Примечание. Так как это будет единственный исполнитель UserService, он будет введен.
  • помимо @Autowired аннотация, весна может использовать XML-конфигурируемый autowiring. В этом случае все поля, имеющие имя или тип, совпадающие с существующим компонентом, автоматически получают введенный компонент. Фактически, это была первоначальная идея autowiring - иметь поля, введенные с зависимостями без какой-либо конфигурации. Другие аннотации, такие как @Inject,@Resource можно также использовать.

зависит от того, прошли ли вы маршрут аннотаций или маршрут определения XML bean.

скажем, у вас были бобы, определенные в вашем applicationContext.xml:

<beans ...>

    <bean id="userService" class="com.foo.UserServiceImpl"/>

    <bean id="fooController" class="com.foo.FooController"/>

</beans>

автопроводка происходит при запуске приложения. Итак, в fooController, который для Аргументов ради хочет использовать UserServiceImpl класс, вы бы аннотировать его следующим образом:

public class FooController {

    // You could also annotate the setUserService method instead of this
    @Autowired
    private UserService userService;

    // rest of class goes here
}

, когда он видит @Autowired, Spring будет искать класс, соответствующий свойству в applicationContext, и вводить его автоматически. Если у вас есть более 1 компонента UserService, то вам нужно будет определить, какой из них следует использовать.

если вы делаете следующее:

UserService service = new UserServiceImpl();

он не будет поднимать @Autowired, если вы не установите его самостоятельно.

@Autowired является аннотацией, введенной весной 2.5, и она используется только для инъекций.

например:

class A {

    private int id;

    // With setter and getter method
}

class B {

    private String name;

    @Autowired // Here we are injecting instance of Class A into class B so that you can use 'a' for accessing A's instance variables and methods.
    A a;

    // With setter and getter method

    public void showDetail() {
        System.out.println("Value of id form A class" + a.getId(););
    }
}

как @Autowired работает внутри?

Ex -

class EnglishGreeting {
   private Greeting greeting;
   //setter and getter
}

class Greeting {
   private String message;
   //setter and getter
}

.xml-файл будет выглядеть одинаково, если не использовать @Autowired

<bean id="englishGreeting" class="com.bean.EnglishGreeting">
   <property name="greeting" ref="greeting"/>
</bean>

<bean id="greeting" class="com.bean.Greeting">
   <property name="message" value="Hello World"/>
</bean>

если вы используете @Autowired, то

class EnglishGreeting {
   @Autowired //so automatically based on the name it will identify the bean and inject.
   private Greeting greeting;
   //setter and getter
}

.xml-файл будет выглядеть одинаково, если не использовать @Autowired

<bean id="englishGreeting" class="com.bean.EnglishGreeting"></bean>

<bean id="greeting" class="com.bean.Greeting">
   <property name="message" value="Hello World"/>
</bean>

если все еще есть некоторые сомнения, то пройдите ниже live demo

как @Autowired работает внутри ?

@Autowired

  • отмечает конструктор, поле, метод сеттера или метод конфигурации как быть autowired средствами инъекции зависимости Spring.

  • только один конструктор (максимум) любого данного класса bean может нести это аннотация, указывающая конструктор для autowire при использовании в качестве Весенняя фасоль. Такой конструктор не обязательно должен быть публичным.

  • поля вводятся сразу после окончания строительства объекта, перед любым вызываются методы конфигурации. Такое поле конфигурации не обязательно должно быть общественный.

  • Config методы могут иметь произвольное имя и любое количество аргументы; каждый из этих аргументов будет автоматически подключен с совпадением фасоль в весеннем контейнере. Бобовые методы метода set свойства фактически это просто частный случай такого общего метода конфигурации. Такие методы конфигурации не должны быть публичными.

  • в случае нескольких аргументов методов, параметр 'required' является применимо для всех аргументов.

  • в случае типа зависимости коллекции или карты контейнер будет autowire все бобы, соответствующие объявленному типу значения. В случае Map, ключи должны быть объявлены как строка типа и будут разрешены соответствующие имена бобов.

вам просто нужно аннотировать свой класс обслуживания UserServiceImpl с аннотацией

@Service("userService")

контейнер весны позаботится о жизненный цикл этого типа по мере того как он регистрирует как обслуживание.

затем в вашем контроллере вы можете автоматически подключить (создать экземпляр) его и использовать его функциональность.

@Autowired
UserService userService;

Spring dependency inject поможет вам удалить соединение из ваших классов. Вместо того, чтобы создавать такой объект

UserService userService = new UserServiceImpl();

вы будете использовать это после введения DI

@Autowired
private UserService userService;

для достижения этой цели вам необходимо создать компонент вашего сервиса в файле ServiceConfiguration. После этого вам нужно импортировать этот класс ServiceConfiguration в свой класс WebApplicationConfiguration, чтобы вы могли автоматически подключать этот компонент к своему контроллеру, например этот.

public class AccController {

    @Autowired
    private UserService userService;
} 

вы можете найти конфигурацию java на основе POC здесь пример

вся концепция инверсии управления означает, что вы свободны от рутинной работы по созданию экземпляров объектов вручную и предоставлению всех необходимых зависимостей. Когда вы аннотируете класс с соответствующей аннотацией (например,@Service) Spring автоматически создаст экземпляр объекта для вас. Если вы не знакомы с аннотациями, вы также можете использовать XML-файл вместо этого. Тем не менее, это не плохая идея для создания экземпляров классов вручную (с new ключевое слово) в модульных тестах, когда вы не хотите загружать весь весенний контекст.

имейте в виду, что вы должны включить аннотацию @Autowired, добавив элемент <context:annotation-config/> в файл конфигурации spring. Это зарегистрирует AutowiredAnnotationBeanPostProcessor, который заботится о обработке аннотации.

и после этого вы можете autowire ваше обслуживание путем использование метода впрыски поля.

public class YourController{

 @Autowired
 private UserService userService; 

}

Я нашел это из сообщения Spring @autowired аннотация