[Из песочницы] Как я изучаю фреймворк Spring (помощь начинающим — дело рук самих начинающих)

habr.png

Добрый день!

Я поставил себе цель изучить фреймфорк Spring для языка Java. Во время изучения решил проверить на себе алгоритм обучения Ричарда Фейнмана: организовать-упростить-обучить другого. В общем, я стал записывать серию коротких уроков для начинающих по работе в Spring. Для желающих повторить выложил исходный код.

Урок 01. Разбираемся с IoC


Итак, соберем вместе поэтов, пускай сочиняют и читают нам свои стихи.

Для начала объявим интерфейс, генерирующий стихи src\main\java\spring\interfaces\Lyricist.java:

package spring.intarfaces;

public interface Lyricist {
        public String Generate();
}


Реализуем этот интерфейс в классе src\main\java\spring\impls\Mayakovsky.java:

package spring.impls;

import spring.intarfaces.Lyricist;

public class Mayakovsky implements Lyricist {

        @Override
        public String Generate() {
                return "А вы\r\n" + "ноктюрн сыграть\r\n" + "могли бы\r\n" + "на флейте водосточных труб?";
        }

}


Пропишем, что будем создавать конкретный объект Mayakovsky в конфигурационном xml-файле src\main\resources\ApplicationContext.xml:




        



Связали id LyricistBean1 c именем класса Mayakovsky. Почти все готово, не хватает только вызывающего класса src\main\java\spring\main\Start.java:

package spring.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import spring.intarfaces.Lyricist;

public class Start {

        public static void main(String[] args) {
                ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
                Lyricist lyr1 = context.getBean("LyricistBean1", Lyricist.class);
                System.out.println(lyr1.Generate());

                ((ConfigurableApplicationContext) context).close();// закрытие контекста вручную

        }

}


В классе Start мы прочитали наш конфигурационный файл, создали экземпляр поэта по имени бина LyricistBean1. Получили экземпляр поэта Mayakovsky. Функция Generate () вернула нам бессмертные строки:

А вы
ноктюрн сыграть
могли бы
на флейте водосточных труб?

Урок 02. Выбор создаваемого экземпляра через конфигурационный файл


Допустим, друг помог нам и предоставил другую реализацию нашего интерфейса Lyricist src\main\java\spring\impls\Poushkin.java:

package spring.impls;

import spring.intarfaces.Lyricist;

public class Poushkin implements Lyricist {

        @Override
        public String Generate() {
                return "Я помню чудное мгновенье:\r\n" + "Передо мной явилась ты,\r\n" + "Как мимолетное виденье,\r\n"
                                + "Как гений чистой красоты.";
        }

}


Изменим в конфигурационном файле ApplicationContext.xml слово Mayakovsky на слово Poushkin.

Запускаем программу. Получаем без пересборки совсем другой результат:

Я помню чудное мгновенье
Передо мной явилась ты,
Как мимолетное виденье,
Как гений чистой красоты.

Урок 03. Бины в коде, а не в конфигурационном файле


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

Изменим класс Poushkin.java

  1. Добавим импорт библиотеки import org.springframework.stereotype.Component;
  2. Поставим аннотацию Component («LyricistBean1») перед объявлением класса


Таким образом мы намекнули Spring, что хотим в виде первого поэта видеть именно Poushkin, а никак не кого-то другого.

Осталось чуть-чуть исправить конфигурационный файл ApplicationContext.xml:

1. Добавим сверху пространство имен context: xmlns: context=«www.springframework.org/schema/context»;

2. Удалим ненужную строку: />

3. Добавим вместо нее команду автоматически добавлять в программу бины из всех классов, расположенных в каталоге spring.impls:

В итоге файл ApplicationContext.xml должен выглядеть вот так:




           




Запускаем. Получаем тот же результат, что и в предыдущем уроке.

Урок 04. Конфигурационный класс


Избавимся совсем от xml-файла.

Все настройки могут находиться и в java-классе. Иногда это удобно.

Добавим специальный настроечный класс src\main\java\spring\main\LyricistConfiguration.java в нашу программу:

package spring.main;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan(basePackages = { "spring.impls" })
@Configuration
public class LyricistConfiguration {

}


@ComponentScan показывает, в каком каталоге искать бины.
@Configuration сообщает, что наш класс специальный, конфигурационный.

Все, xml-файл больше не нужен. Осталось сообщить эту новость нашему основному классу:

  1. Дополним его нужным импортом import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  2. Заменим строку создания контекста
    ApplicationContext context = new AnnotationConfigApplicationContext (LyricistConfiguration.class);


В итоге главный файл src\main\java\spring\main\Start.java должен выглядеть вот так:

package spring.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import spring.intarfaces.Lyricist;

public class Start {

        public static void main(String[] args) {
                ApplicationContext context = new AnnotationConfigApplicationContext(LyricistConfiguration.class);
                Lyricist lyr1 = context.getBean("LyricistBean1", Lyricist.class);
                System.out.println(lyr1.Generate());

                ((ConfigurableApplicationContext) context).close();// закрытие контекста вручную

        }

}


Все запускается и по-прежнему выдает бессмертные Пушкинские строки. Все работает. Но уже без xml.

Урок 05. Singleton и Prototype


Исследуем возможности конфигурационного файла. Поэтому вернемся пока к проекту из второго урока. Попробуем в Start.java создать два экземпляра класса Poushkin и удостоверимся, что великий поэт один и тот же:

     Lyricist lyr1 = context.getBean("LyricistBean1", Lyricist.class);
        System.out.println(lyr1.Generate());
        System.out.println(lyr1.hashCode());

        Lyricist lyr2 = context.getBean("LyricistBean1", Lyricist.class);
        System.out.println(lyr2.Generate());
        System.out.println(lyr2.hashCode());


И стихи одни и те же, и хэш-код сорпадает. Все в порядке.

Добавим в наш проект простого гражданина, не пишущего стихи src\main\java\spring\impls\SimpleMan.java:

package spring.impls;

import spring.intarfaces.Lyricist;

public class SimpleMan implements Lyricist {

        @Override
        public String Generate() {
                return "Я человек простой, стихов не пишу";
        }

}


Зарегистрируем класс в конфигурационном файле (сразу после первого бина)

 

Пробуем создать

     Lyricist lyr1 = context.getBean("LyricistBean2", Lyricist.class);
        System.out.println(lyr1.Generate());
        System.out.println(lyr1.hashCode());

        Lyricist lyr2 = context.getBean("LyricistBean2", Lyricist.class);
        System.out.println(lyr2.Generate());
        System.out.println(lyr2.hashCode());


Гражданин все время один и тот же. Непорядок…

Изменим регистрацию бина в конфигурационном файле, добавив волшебное слово scope=«prototype»

В итоге файл src\main\resources\ApplicationContext.xml будет выглядеть так:




        
        




Теперь все в порядке. Граждане каждый раз разные. А Пушкин всегда один.

Внимательные заметили, что в первом бине добавилась настройка scope=«singleton», но это настройка используется по умолчанию, поэтому ее можно и не писать.

На сегодня все. Если данный пост пройдет премодерацию, а у меня появятся время и силы, будет продолжение про AOP, JDBC, транзакции, MVC и прочие премудрсти.

С уважением, Владимир

© Habrahabr.ru