Pro Spring 4
Жизненный цикл Spring Bean
InitializingBean
Вызывается метод afterPropertiesSet(), который служит той же цели, что и метод init()
@PostConstruct
Начиная с версии Spring 2.5, поддерживаются также и аннотации JSR-250 для указания метода, который платформа Spring должна вызвать, если соответствующая аннотация, связанная с жизненным циклом бина, существует в классе. Это тот же init-method, только имя метода может быть любым. Для работы необходимо добавить дескриптор context:annotation-config.
DisposableBean
Вызывается метод destroy(), который служит той же цели, что и метод указываемый в атрибуте destroy-metod.
@PreDestroy
Применение аннотации жизненного цикла @PreDestroy, определенной в стандарте JSR-250, которая является противоположностью @PostConstruct. Для работы необходимо добавить дескриптор context:annotation-config.
Конфигурация XML
beans
beans default-lazy-init
Атрибут инструктирует Spring о том, что экземпляры бинов, определенных в конфигурационном файле, должны создаваться только при их запросе приложением.
<beans ... default-lazy-init = "true"> <bean ... /> ... </beans>
context:component-scan
Дескриптор <context:component-scan> сообщает Spring о необходимости сканирования кода на предмет внедряемых бинов, аннотированных с помощью @Component, @Controller, @Repository и @Service, а также поддерживающих аннотации @Autowired и @Inject в указанном пакете (и всех eгo внутренних па кетах). В дескрипторе <context:component-scan> можно определить множество пакетов, используя в качестве разделителя запятую, точку запятой или пробел. Кроме того, для более детализированного управления этот дескриптор поддерживает включение и исключение сканирования компонентов. Также можно указать пакет для сканирования через установку атрибута base-package. Еще можно указать исключения через context:exclude-filter.
bean
bean/property
name - Имя свойства бина value - значение (простой тип)
До версии 2.5:
ref - ссылка на другой бин по id
Применение атрибута local означает, что дескриптор ref всегда просматривает только идентификатор бина и никогда не принимает во внимание его псевдонимы:
<ref local="test"/>
Более того, определение бина должно существовать в том же самом ХМL-файле конфигурации.
Пример ссылки на бин (ссылка текущий, дочерний, родительский контекст)
<ref bean="newBean"/>
Пример ссылки на бин родительского контекста
<ref parent="newBean"/>
С версии 2.5: конфигурировать можно не через property, а в самом bean так:
p:<тут имя свойства>-ref="id другого бина"
или так
p:<тут имя свойства>="простое значение"
Через SpEL:
p:name = "#{injectSimpleConfig.name}"
bean/property/map
Пример:
<property name="map"> <map> <entry key="v1"> <value>Hello World!</value> </entry> <entry key="refToBean"> <ref local="localBeanId"/> </entry> </map> </property>
bean/property/set
<property name="set"> <set> <value>Hello World 1 </value> <ref local="oracle" /> </set> </property>
bean/property/list
<property name="list"> <list> <value>Hello World!</value> <ref local="localBeanId"/> </list> </property>
bean/property/props
Дескриптор <props> позволяет передавать в качестве значений только String, потому что класс Properties разрешает только значения свойств типа String. Пример:
<property name="props"> <props> <prop key="firstName">Sasha</prop> <prop key="secondName">V.</prop> </props> </property>
bean/constructor-arg
До версии 3.1: constructor-arg определяет Constructor Injection. Всегда лучше применять атрибут index, чтобы избежать путаницы между параметрами.
С версии 3.1: можно применять в bean выражение вида c:<свойство>=<значение> или _<digit> - как указание индекса аргумента конструктора
<bean id="message" class="java.lang.String" с:_O="message"/>
Если есть 2 конструктора с одинаковыми именами параметров, то можно указать тип
<constructor-arg type="int"><value>1</value><constructor-arg>
bean/lookup-method
Пример Method Injection:
<bean id="abstractLookupBean" class="com.a.AЬstractLookupDemoBean"> <lookup-method name="getMyHelper" bean="helper"/> </bean>
bean/replaced-method
<bean id="replacementTarget" class="com.a.ReplacementTarget"> <replaced-method name="formatMessage" replacer="methodReplacer"> <arg-type>String</arg-type> </replaced-method> </bean>
bean name-алиасы
Через name:
<bean id="name1" name="name2 name3,name4;name5" class="java.lang.String"/>
Через alias:
<alias name = "namel" alias = "name6"/>
Извлечь список псевдонимов бина можно с помощью вызова метода ApplicationContext.getAliases(String) с передачей ему любого из имен бина или его идентификатора. Этот метод возвращает в виде массива String список псевдонимов, содержащий все псевдонимы кроме указанного при вызове.
bean scope
По умолчанию Spring устанавливает атрибут scope в singleton (одиночный). Область действия на уровне prototype (прототип) заставляет Spring создавать новый экземпляр бина каждый раз, когда он запрашивается приложением. Пример:
<bean id="nonSingleton" class="java.lang.String" scope="prototype" c:_0="Sasha V."/>
bean depends-on
В следующей конфигурации мы утверждаем, что бин по имени beanA зависит от бина под названием beanB.
<bean id="beanA" class="BeanA" depends-on="beanB"/> <bean id="beanB" class="BeanB"/>
Во время разработки приложений такого подхода лучше избегать; вместо этого определяйте зависимости с помощью контрактов Setter Injection и Constructor Injection.
bean autowire
В атрибуте autowire для бина понадобится указать используемый режим автосвязывания. Платформа Spring поддерживает следующие режимы автосвязывания: byName, ЬуТуре, constructor, default и no (автосвязывание отключено; устанавливается по умолчанию).
bean lazy-init
Атрибут lazy-init устанавливается в true, чтобы информировать Spring о необходимости создания экземпляра бина только при первом его запросе, а не во время начальной загрузки.
bean parent
Наследование бинов:
<bean id="inheritParent" class="SimpleBean" p:name="Name1" p:age="32"/> <bean id="inheritChild" class="SimpleBean" parent="inheritParent" р:аgе="ЗЗ"/>
bean abstract
В случае если определение родительского бина не должно быть доступным для поиска из ApplicationContext, к дескриптору bean, объявляющему родительский бин, можно добавить атрибут abstract="true".
bean init-method
Атрибут init-method, который сообщает платформе Spring, что она должна вызвать метод init(), как только завершит конфигурирование бина.
<bean id="iBean" class="BeanClass" init-method="init"/>
Аналоги: InitializingBean.afterPropertiesSet(), @PostConstruct
bean destroy-method
Чтобы назначить метод для вызова во время уничтожения бина, нужно просто указать имя этого метода в атрибуте destroy-method дескриптора <bean> для бина. Платформа Spring вызывает этот метод непосредственно перед уничтожением одиночного экземпляра бина (она не будет вызывать этот метод для бинов с областью действия на уровне прототипа).
<bean id="dBean" class="BeanClass" destroy-method="destroy"/>
Аналоги: DisposableBean.destroy(), @PreDestroy
bean factory-bean
Иногда нужно создавать экземпляры компонентов JavaBean, которые были предоставлены приложением третьей стороны, не поддерживающим Spring. Вы не знаете, как создавать экземпляр этого класса, но вам известно, что приложение третьей стороны предлагает класс, который можно использовать для получения экземпляра JavaBean, необходимого вашему приложению Spring.
<bean id="defaultDigest" factory-bean="defaultDigestFactory" factory-method="createinstance"/>
util
Пространство имен util, предоставляемое Spring, для объявления бинов, хранящих свойства коллекций.
util:map
<util:map id="map" map-class = "java.util.HashMap"> <entry key = "someValue"> <value>Hello World!</value> </entry> <entry key="someBean"> <ref bean="beanId"/> </entry> </util:map>
util:properties
<util:properties id="props"> <prop key="firstName">Sasha</prop> <prop key = "secondName">V.</prop> </util:properties>
util:set
<util: set id="set"> <value>Hello World!</value> <ref bean = "oracle"/> </util: set>
util:list
<util:list id="list"> <value>Hello World!</value> <ref bean="oracle"/> </util:list>
Кофигурация аннотациями
@Autowired
Если указано на setter, то происходит автоматическое связывание.
Если указано на construcor, то происходит автоматическая передача параметра, пример:
@Autowired public NewConstructor (@Value ( "message") String message) { this.message = message; }
Аннотация @Autowired может быть применена только к одному из методов конструкторов.
@Inject
В спринг аналогична автоматическому связыванию (JSR-299).
@Resource
Пример - @Resource (name = "messageProvider") указывается для поддержки автоматического связывания. (JSR-250)
@Value
Предназначена для определения значения, подлежащего внедрению. Свойства:
@Value("32") private int age;
Через SpEL:
@Value("#{injectSimpleConfig.name}")
Жесткое кодирование значения не является удачной идеей, т.к. его изменение влечет за собой перекомпиляцию программы.
@Service
Пример - @Service("messageRenderer") указывает, что этот бин предоставляет службы, которые могут требоваться другим бинам; в качестве параметра аннотации передается имя бина.
@Component
@Component("injectSimpleConfig") @Service является специализацией @Component, отражающей тот факт, что аннотированный класс предоставляет бизнес-службу другим уровням внутри приложения.
Классы Spring
ProtertyEditor
ByteArrayPropertyEditor - String в массив байтов
ClassEditor - полностью определенное имя класса в экземпляр Class
CustomВooleanEditor - в Jаvа-тип Boolean
CustomCollectionEditor - в целевой тип Collection
CustomDateEditor - в значение java.util.Date. Этот редактор с желаемым форматом даты необходимо зарегистрировать в ApplicationContext.
CustomNumberEditor - в числовое значение, которым может быть Integer, Long, Float или Double
FileEditor - в экземпляр File
InputStreamEditor - строковое представление ресурса (например, файлового ресурса вида file: D: /temp/test. txt или classpath:test. txt) в свойство входного потока
LocaleEditor - строковое представление локали, такое как en-GB, в экземпляр java.util.Locale
Pattern - в JDК-объект Pattern или наоборот
PropertiesEditor - строку в формате ключl=значениеl ключ2=значение2 ключn=значениеn в экземпляр java.util.Properties с настройкой соответствующих свойств
StringTrimmerEditor - усечение строковых значений перед внедрением. Этот редактор свойств должен быть явно зарегистрирован в ApplicationContext.
URLEditor - строковое представление URL в экземпляр java.net.URL
CustomEditorConfigurer
В JDK 5 или более новых версиях предлагается класс PropertyEditorSupport, который могут расширять специальные редакторы свойств, оставляя вам реализацию только одного метода setAsText(). Чтобы особый класс редактора можно было применять в приложении, его понадобится зарегистрировать в ApplicationContext с использованием CustomEditorConfigurer.
StopWatch
org.springframework.util.StopWatch - этот класс очень полезный в ситуациях, когда необходимо проводить простые оценки производительности и тестировать разрабатываемые приложения.
StopWatch stopWatch = new StopWatch(); stopWatch.start("demo"); for (int х = О; х < 100000; х++) { MyHelper helper = bean.getMyHelper(); helper.doSomethingHelpful(); } stopWatch.stop(); System. out. println ( "100000 gets took " + stopWatch. getTotalTimeMillis () + " ms");
AbstractApplicationContext
AbstractApplicationContext.registerShutdownHook
registerShutdownHook - создать перехватчик завершения (shutdown hook) - поток, который выполняется непосредственно перед завершением приложения. Это отличный способ вызвать метод destroy () вашего класса AbstractApplicationContext (который расширяется всеми конкретными реализациями ApplicationContext).
Пример для автономного приложения:
ctx.load("classpath:META-INF/spring/app-context-annotation.xml"); ctx.registerShutdownHook(); ctx.refresh();
Можно определить бин, который автоматом сделает тоже самое
<bean id="shutdownHook" class="ShutdownHookBean"/>
где ShutdownHookBean implements ApplicationContextAware с таким методом setApplicationContext:
if (ctx instanceof GenericApplicationContext) { ((GenericApplicationContext)ctx).registerShutdownHook(); }
AbstractApplicationContext.destroy
Единственный недостаток обратных вызовов уничтожения в Spring связан с тем, что они не запускаются автоматически, т.е. перед закрытием приложения нужно не забыть вызвать AbstractApplicationContext.destroy(). Когда приложение выполняется как сервлет, указанный метод destroy() можно вызвать в методе destroy() сервлета. Однако в автономном приложении все не так просто, особенно при наличии множества точек выхода из приложения. К счастью, решение есть. Java позволяет создать перехватчик завершения (shutdown hook). См. AbstractApplicationContext.registerShutdownHook
BeanNameAware
Интерфейс BeanNameAware, который бин может реализовать, чтобы получить свое имя, имеет единственный метод: setBeanName (String)
ApplicationContextAware
Интерфейс ApplicationContextAware, который бин может реализовать, чтобы получить ссылку на контекст ApplicationContext, который их сконфигурировал. Имеет метод: setApplicationContext(ApplicationContext ctx) throws BeansException
FactoryBean
В интерфейсе FactoryBean объявлены три метода: getObject(), getObjectType() и isSingleton(). Реализуя этот интерфейс и добавив в него управляющее свойство, можно создавать бины с соответствующего типа, которые будут возвращаться через getObject(). Пример получения нужного типа объекта:
MessageDigest digest = (MessageDigest)ctx.getBean("shaDigest");
Пример получения фабрики бинов для генерации нужного объекта вручную:
MessageDigestFactoryBean factoryBean = (MessageDigestFactoryBean)ctx.getBean("&shaDigest");
MessageSource
Реализации: ApplicationContext, ResourceBundleMessageSource, ReloadableResourceBundleMessageSource и StaticMessageSource.
Реализация StaticMessageSource не должна применяться в производственном приложении, поскольку ее нельзя конфигурировать внешне.
Реализация ResourceBundleMessageSource загружает сообщения с использованием Jаvа-класса ResourceBundle.
Реализация ReloadableResourceBundleMessageSource в основном такая же, но поддерживает запланированную перезагрузку лежащих в основе исходных файлов.
Все три реализации MessageSource также реализуют еще один интерфейс по имени HierarchicalMessageSource, который позволяет вкладывать друг в друга экземпляры MessageSource.
Чтобы задействовать поддержку MessageSource, предоставляемую ApplicationContext, в конфигурации должен быть определен бин типа MessageSource с именем messageSource. Контекст ApplicationContext берет этот MessageSource и вкладывает его внутрь себя самого, разрешая доступ к сообщениям с применением ApplicationContext. Пример:
<bean id = "messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" p:basenames-ref = "basenames"/> <util:list id="basenames"> <value>buttons</value> <value>labels</value> </util:list>
Файлы должны называться labels_en.properties labels_ru.properties и buttons_en.properties buttons_ru.properties.