Поиск по сайту:

Spring IoC, учебное пособие по Spring Bean


Добро пожаловать в учебник по примерам Spring IoC. Spring Framework построен по принципу инверсии управления. Внедрение зависимостей — это метод реализации IoC в приложениях.

Весенний ИОК

  1. Весна IoC
  2. Весенняя фасоль
  3. Области действия Spring Bean
  4. Конфигурация компонента Spring
  5. Пример Spring IoC и Spring Bean
    1. Конфигурация компонента Spring на основе XML
    2. Конфигурация компонента Spring на основе аннотаций
    3. Конфигурация Spring Bean на основе Java

    Контейнер Spring IoC

    Spring IoC — это механизм для достижения слабой связи между зависимостями объектов. Для достижения слабой связи и динамического связывания объектов во время выполнения зависимости объектов внедряются другими объектами ассемблера. Контейнер Spring IoC — это программа, которая внедряет зависимости в объект и делает его готовым для использования. Мы уже рассмотрели, как мы можем использовать Spring Dependency Injection для реализации IoC в наших приложениях. Классы контейнеров Spring IoC являются частью пакетов org.springframework.beans и org.springframework.context. Контейнер Spring IoC предоставляет нам различные способы разделения зависимостей объектов. BeanFactory — это корневой интерфейс контейнера Spring IoC. ApplicationContext — это дочерний интерфейс интерфейса BeanFactory, который предоставляет возможности Spring AOP, i18n и т. д. Некоторые из полезных дочерних интерфейсов ApplicationContext — это ConfigurableApplicationContext и WebApplicationContext. Spring Framework предоставляет ряд полезных классов реализации ApplicationContext, которые мы можем использовать для получения контекста Spring, а затем Spring Bean. Вот некоторые из полезных реализаций ApplicationContext, которые мы используем;

    • AnnotationConfigApplicationContext: если мы используем Spring в автономных приложениях Java и используем аннотации для конфигурации, мы можем использовать это для инициализации контейнера и получения объектов bean.
    • ClassPathXmlApplicationContext: если у нас есть XML-файл конфигурации bean-компонента Spring в автономном приложении, мы можем использовать этот класс для загрузки файла и получения объекта-контейнера.
    • FileSystemXmlApplicationContext: аналогичен ClassPathXmlApplicationContext, за исключением того, что файл конфигурации xml можно загрузить из любой точки файловой системы.
    • AnnotationConfigWebApplicationContext и XmlWebApplicationContext для веб-приложений.

    Обычно, если вы работаете над приложением Spring MVC и ваше приложение настроено на использование Spring Framework, контейнер Spring IoC инициализируется при запуске приложения, а когда запрашивается bean-компонент, зависимости внедряются автоматически. Однако для автономного приложения вам необходимо инициализировать контейнер где-то в приложении, а затем использовать его для получения компонентов Spring.

    Весенняя фасоль

    В Spring Bean нет ничего особенного, любой объект в среде Spring, который мы инициализируем через контейнер Spring, называется Spring Bean. Любой нормальный класс Java POJO может быть Spring Bean, если он настроен на инициализацию через контейнер, предоставляя информацию о метаданных конфигурации.

    Спринг Бин Сферы

    Для Spring Beans определено пять областей.

    1. singleton — для каждого контейнера будет создан только один экземпляр компонента. Это область действия по умолчанию для spring bean-компонентов. При использовании этой области убедитесь, что у bean-компонента нет общих переменных экземпляра, иначе это может привести к проблемам с несогласованностью данных.
    2. прототип — новый экземпляр будет создаваться каждый раз, когда запрашивается компонент.
    3. запрос. Это то же самое, что и область действия прототипа, однако она предназначена для использования в веб-приложениях. Для каждого HTTP-запроса будет создаваться новый экземпляр компонента.
    4. session — новый компонент будет создаваться контейнером для каждого HTTP-сеанса.
    5. global-session — используется для создания глобальных сеансовых компонентов для приложений с портлетами.

    Spring Framework является расширяемым, и мы также можем создавать свои собственные области видимости. Тем не менее, в большинстве случаев мы хорошо справляемся с областями действия, предоставляемыми фреймворком.

    Конфигурация Spring Bean

    Spring Framework предоставляет три способа настройки bean-компонентов для использования в приложении.

    1. Конфигурация на основе аннотаций — с помощью аннотации @Scope.
    2. Конфигурация на основе XML — путем создания XML-файла конфигурации Spring для настройки bean-компонентов. Если вы используете среду Spring MVC, конфигурацию на основе XML можно загрузить автоматически, написав некоторый шаблонный код в файле web.xml.
    3. Конфигурация на основе Java. Начиная с Spring 3.0, мы можем настраивать компоненты Spring с помощью программ Java. Некоторые важные аннотации, используемые для конфигурации на основе Java, — это @Bean.

    Пример проекта Spring IoC и Spring Bean

    Конфигурация Spring Bean на основе XML

    MyBean — это простой класс Java POJO.

    package com.journaldev.spring.beans;
    
    public class MyBean {
    
    	private String name;
    	
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    }
    

    XML-файл конфигурации Spring

    код servlet-context.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="https://www.springframework.org/schema/mvc"
    	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
    	xmlns:beans="https://www.springframework.org/schema/beans"
    	xmlns:context="https://www.springframework.org/schema/context"
    	xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
    		https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
    		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    	
    	<!-- Enables the Spring MVC @Controller programming model -->
    	<annotation-driven />
    
    	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    	<resources mapping="/resources/**" location="/resources/" />
    
    	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<beans:property name="prefix" value="/WEB-INF/views/" />
    		<beans:property name="suffix" value=".jsp" />
    	</beans:bean>
    	
    	<context:component-scan base-package="com.journaldev.spring" />
    	
    	<beans:bean name="myBean" class="com.journaldev.spring.beans.MyBean" scope="singleton" ></beans:bean>
    	
    </beans:beans>
    

    Обратите внимание, что MyBean настраивается с использованием элемента bean с областью действия как singleton.

    Конфигурация Spring Bean на основе аннотаций

    package com.journaldev.spring.beans;
    
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Service;
    import org.springframework.web.context.WebApplicationContext;
    
    @Service
    @Scope(WebApplicationContext.SCOPE_REQUEST)
    public class MyAnnotatedBean {
    
    	private int empId;
    
    	public int getEmpId() {
    		return empId;
    	}
    
    	public void setEmpId(int empId) {
    		this.empId = empId;
    	}
    	
    }
    

    MyAnnotatedBean настраивается с помощью @Service, а для области действия задано значение Request.

    Класс контроллера Spring IoC

    Класс HomeController будет обрабатывать HTTP-запросы для домашней страницы приложения. Мы будем внедрять наши компоненты Spring в этот класс контроллера через контейнер WebApplicationContext.

    package com.journaldev.spring.controller;
    
    import java.text.DateFormat;
    import java.util.Date;
    import java.util.Locale;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    import com.journaldev.spring.beans.MyAnnotatedBean;
    import com.journaldev.spring.beans.MyBean;
    
    @Controller
    @Scope("request")
    public class HomeController {
    		
    	private MyBean myBean;
    	
    	private MyAnnotatedBean myAnnotatedBean;
    
    	@Autowired
    	public void setMyBean(MyBean myBean) {
    		this.myBean = myBean;
    	}
    
    	@Autowired
    	public void setMyAnnotatedBean(MyAnnotatedBean obj) {
    		this.myAnnotatedBean = obj;
    	}
    	
    	/**
    	 * Simply selects the home view to render by returning its name.
    	 */
    	@RequestMapping(value = "/", method = RequestMethod.GET)
    	public String home(Locale locale, Model model) {
    		System.out.println("MyBean hashcode="+myBean.hashCode());
    		System.out.println("MyAnnotatedBean hashcode="+myAnnotatedBean.hashCode());
    		
    		Date date = new Date();
    		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
    		
    		String formattedDate = dateFormat.format(date);
    		
    		model.addAttribute("serverTime", formattedDate );
    		
    		return "home";
    	}
    	
    }
    

    Дескриптор развертывания

    Нам нужно настроить наше приложение для Spring Framework, чтобы метаданные конфигурации загружались, а контекст был инициализирован.

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
    	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    
    	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>/WEB-INF/spring/root-context.xml</param-value>
    	</context-param>
    	
    	<!-- Creates the Spring Container shared by all Servlets and Filters -->
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    
    	<!-- Processes application requests -->
    	<servlet>
    		<servlet-name>appServlet</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    		
    	<servlet-mapping>
    		<servlet-name>appServlet</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    
    </web-app>
    

    Почти вся приведенная выше конфигурация представляет собой шаблонный код, сгенерированный инструментом STS автоматически.

    Запустите пример приложения Spring IoC Bean

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

    MyBean hashcode=118267258
    MyAnnotatedBean hashcode=1703899856
    MyBean hashcode=118267258
    MyAnnotatedBean hashcode=1115599742
    MyBean hashcode=118267258
    MyAnnotatedBean hashcode=516457106
    

    Обратите внимание, что MyBean настроен как одноэлементный, поэтому контейнер всегда возвращает один и тот же экземпляр, а хэш-код всегда один и тот же. Точно так же для каждого запроса создается новый экземпляр MyAnnotatedBean с другим хэш-кодом.

    Конфигурация Spring Bean на основе Java

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

    package com.journaldev.spring.main;
    
    import java.util.Date;
    
    public class MyService {
    
    	public void log(String msg){
    		System.out.println(new Date()+"::"+msg);
    	}
    }
    

    MyService — это простой класс Java с некоторыми методами.

    package com.journaldev.spring.main;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan(value="com.journaldev.spring.main")
    public class MyConfiguration {
    
    	@Bean
    	public MyService getService(){
    		return new MyService();
    	}
    }
    

    Класс конфигурации на основе аннотаций, который будет использоваться для инициализации контейнера Spring.

    package com.journaldev.spring.main;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class MyMainClass {
    
    	public static void main(String[] args) {
    		
    		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
    				MyConfiguration.class);
    		MyService service = ctx.getBean(MyService.class);
    		
    		service.log("Hi");
    		
    		MyService newService = ctx.getBean(MyService.class);
    		System.out.println("service hashcode="+service.hashCode());
    		System.out.println("newService hashcode="+newService.hashCode());
    		ctx.close();
    	}
    
    }
    

    Простая тестовая программа, в которой мы инициализируем контекст AnnotationConfigApplicationContext, а затем используем метод getBean() для получения экземпляра MyService. Обратите внимание, что я вызываю метод getBean два раза и печатаю хэш-код. Поскольку для MyService не определена область действия, он должен быть одноэлементным, и, следовательно, хэш-код должен быть одинаковым для обоих экземпляров. Когда мы запускаем вышеуказанное приложение, мы получаем следующий вывод консоли, подтверждающий наше понимание.

    Sat Dec 28 22:49:18 PST 2013::Hi
    service hashcode=678984726
    newService hashcode=678984726
    

    Если вы ищете конфигурацию на основе XML, просто создайте файл конфигурации Spring XML, а затем инициализируйте контекст с помощью следующего фрагмента кода.

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                    "applicationContext.xml");
            MyService app = context.getBean(MyService.class);
    

    Это все, что касается руководства по примерам Spring IoC, деталей Spring Bean Scopes и Configuration. Загрузите пример проекта Spring IoC и Spring Bean по ссылке ниже и поэкспериментируйте с ним для лучшего понимания.

    Скачать проект Spring Beans

    Ссылка: Страница Spring.IO для IOC