Создание XML конфигурации Spring в файле applicationContext.xml, файл должен лежать в папке resources
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<!-- <bean ...>...</bean> -->
</bean>
Внедряемый бин
<bean id="testBean" // уникальный индегфикатор бина
class="com.suleimanov.core.TestBean">
</bean>
public TestBean(String name){ this.name = name; }
// applicationContext.xml
<bean id="testBean" class="com.suleimanov.core.TestBean">
<constructor-arg value="Niko"/>
</bean>
public MusicPlayer(RockMusic music) { this.music = music; }
<!-- applicationContext.xml -->
<bean id="musicBean" class="com.suleimanov.core.RockMusic"></bean>
<bean id="musicPlayer" class="com.suleimanov.core.MusicPlayer">
<constructor-arg ref="musicBean"/>
</bean>
Внедрение ссылки на объект
public void setMusic(Music music) { this.music = music; }
<!-- applicationContext.xml -->
<bean id="musicBean" class="com.suleimanov.core.ClassicalMusic"></bean>
<bean id="musicPlayer" class="com.suleimanov.core.MusicPlayer">
<property name="music" ref="musicBean"/>
<!-- name - имя сеттера с маленькой буквы -->
</bean>
Внедрение простых значений
public void setName(String name) { this.name = name; }
public void setVolume(String volume) { this.volume = volume; }
<bean id="musicPlayer" class="com.suleimanov.core.MusicPlayer">
<property name="name" value="Some name"/>
<property name="volume" value="50"/>
</bean>
расширение файла .properties в каталоге resources
<!-- beans.properties -->
musicPlayer.name = Some name
musicPlayer.volume = 70
<!-- applicationContext.xml -->
<context:property-placeholder location="classpath:beans.properties"/>
<!--classpath: - папка resources -->
<bean id="musicPlayer" class="com.suleimanov.core.MusicPlayer">
<property name="name" value="${musicPlayer.name}"/>
<property name="volume" value="${musicPlayer.volume}"/>
</bean>
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
TestBean testBean = context.getBean("testBean", TestBean.class);
System.out.println(testBean.getName());
context.getBean - получение бина, в качетсве первого бина указывается id бина, в качетсве второго тот класс бин которого хотим получить
Spring определяет 6 типов областей видимости:
- singleton
- prototype
- request
- session
- application
- websocket
request, session, application и websocket, доступны только в веб-приложении.
bean-компонент с областью singleton
, контейнер создает один экземпляр этого бина. Все запросы для этого имени компонента будут возвращать один и тот же объект, который кэшируется. Любые изменения объекта будут отражены во всех ссылках на компонент.
Эта область является значением по умолчанию, если не указана другая область.
<bean id="musicPlayer" class="com.suleimanov.core.ClassicalMusic"
scope="singleton"> <!-- singleton указывать не обязательно --->
</bean>
MusicPlayer musicPlayer1 = context.getBean("musicPlayer", MusicPlayer.class);
MusicPlayer musicPlayer2 = context.getBean("musicPlayer", MusicPlayer.class);
System.out.println(musicPlayer1); // com.suleimanov.core.MusicPlayer@795cd85e
System.out.println(musicPlayer2); // com.suleimanov.core.MusicPlayer@795cd85e
System.out.println(musicPlayer2.getVolume()); // 70
musicPlayer1.setVolume(10);
System.out.println(musicPlayer2.getVolume()); // 10
Бин с областью действия prototype
будет возвращать другой экземпляр каждый раз, когда запрашивается из контейнера.
scope="prototype"
MusicPlayer musicPlayer1 = context.getBean("musicPlayer", MusicPlayer.class);
MusicPlayer musicPlayer2 = context.getBean("musicPlayer", MusicPlayer.class);
System.out.println(musicPlayer1); // com.suleimanov.core.MusicPlayer@402bba4f
System.out.println(musicPlayer2); // com.suleimanov.core.MusicPlayer@795cd85e
System.out.println(musicPlayer2.getVolume()); // 70
musicPlayer1.setVolume(10);
System.out.println(musicPlayer2.getVolume()); // 70
Жизненный цикл любого бина (объекта) означает: как и когда он появляется, как он себя ведет во время жизни и как и когда он исчезает.
Жизненным циклом управляет спринг-контейнер. После запуска приложения запускается именно он. После этого контейнер по необходимости и в соответствии с запросами создает экземпляры бинов и внедряет необходимые зависимости. Затем бины, связанные с контейнером, уничтожаются когда контейнер завершает свою работу. Поэтому, если мы хотим выполнить какой-то код во время инстанцирования бина или сразу после завершения работы контейнера, то вынесим его в специальные init()
и destroy()
методы.
init
- метод, который запускается в ходе инициализации бина. Можно использовать для настройки ресурсов, таких как БД/сокет/файл и т.д.
destroy
- метод, который запускается в ходе угичтожения бина (при завершения приложения). Можно использовать для очищения ресурсов, закрытия потока ввода-вывода, закрытие доступа к БД.
public class ClassicalMusic implements Music {
@Override
public String getSong() { return "Classical Music"; }
private void doInit() { System.out.println("Doing my initialization"); }
private void doDestroy() { System.out.println("Doing my destruction"); }
}
applicationContext.xml
<bean id="musicBean"
class="com.suleimanov.core.ClassicalMusic"
init-method="doInit"
destroy-method="doDestroy"
</bean>
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ClassicalMusic classicalMusic = context.getBean("musicBean", ClassicalMusic.class);
System.out.println(classicalMusic.getSong());
context.close();
// Doing my initialization
// Classical Music
// Doing my destruction
Тонокости:
- может быть любой модификатор доступа (public, protected, private)
- нельзя получить тип возращаемого, поэтому обычно void
- методы не должны получать на вход какие-либо аргументы
- spring не вызывает
destroy
метод для бинов со scope "prototype"
Фабричный метод - это паттерн программирования. Этот паттерн предлагает создавать объект не напрямую, используя оператор new, а через вызов особового фабричного метода. Объекты по-прежнему будут создаваться при помощи оператора new, но он вызывается из фабричного метода.
public class ClassicalMusic implements Music {
private ClassicalMusic() {}
public static ClassicalMusic getClassicalMusic(){ // обязательно static
return new ClassicalMusic();
}
@Override
public String getSong() { return "Classical Music"; }
}
applicationContext.xml
<bean id="musicBean"
class="com.suleimanov.core.ClassicalMusic"
factory-method="getClassicalMusic">
</bean>
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ClassicalMusic classicalMusic = context.getBean("musicBean", ClassicalMusic.class);
System.out.println(classicalMusic.getSong());
context.close();
// Classical Music