Pro Spring 4

Материал из Home Wiki
Перейти к: навигация, поиск

Содержание

Жизненный цикл Spring Bean

SpringBeanLifeCycle.png

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>

beans profile

Профиль заставляет Spring конфигурировать только тот контекст ApplicationContext, который определен, когда указанный профиль становится активным. Активируется опцией -Dspring.profiles.active=activeProfile Пример профиля:

 <beans xmlns = "http://www.springframework.org/schema/beans"
       xmlns:xsi = "http://www.wЗ.org/2001/XМLSchema-instance"
       xsi:schemaLocation = "http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd"
       profile = "profile1">
      ...
     </beans>

см. Environment

context:component-scan

Дескриптор <context:component-scan> сообщает Spring о необходимости сканирования кода на предмет внедряемых бинов, аннотированных с помощью @Component, @Controller, @Repository и @Service, а также поддерживающих аннотации @Autowired и @Inject в указанном пакете (и всех eгo внутренних па­ кетах). В дескрипторе <context:component-scan> можно определить множест­во пакетов, используя в качестве разделителя запятую, точку запятой или пробел. Кроме того, для более детализированного управления этот дескриптор поддержи­вает включение и исключение сканирования компонентов. Также можно указать пакет для сканирования через установку атрибута base-package. Еще можно указать исключения через context:exclude-filter.

context:property-placeholder

Дескриптор context:property-placeholder для загрузки свойств в Sрring-интерфейс Environment, который помещен в оболочку интерфейса ApplicationContext. Кроме того, мы применяем заполнители для внедрения зна­чений в бин AppProperty.

 <context:property-placeholder location="classpath:application.properties"/>
     <bean id="appProperty" class="AppProperty">
       <property name="applicationHome" value="${application.home}"/>
       <property name="userHome" value="${user.home}"></property>
     </bean>

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"/>

bean factory-method

см. bean factory-bean

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>

aop

aop:aspectj-autoproxy - включение АОП с использованием аннотаций, см. АОП с аннотациями

  <aop:config>
    <aop:pointcut id="fooExecution" expression="execution(* foo*(int))"/>
    <aop:aspect ref = "advice">
      <aop:before pointcut-ref="fooExecution" method="simpleBeforeAdvice"/>
    </aop:aspect>
  </aop:config>
  <bean id="advice" class="MyAdvice"/>
  <bean id="myDependency" class="MyDependency"/>
  <bean id="myBean" class="MyBean">
    <property name="dep" ref="myDependency"/>
  </bean>

aop:before - до запуска (приоритет выполнения перед arount)

аор:around - вокруг запуска

aop:after-returning - после возврата, работает в случае отсутствия исключения

aop:after - после, работает и в случае отсутствия исключения и в случае наличия исключения

Кофигурация аннотациями

@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, отражающей тот факт, что аннотированный класс предоставляет бизнес-службу другим уровням внутри приложения.

@Configuration

Аннотация @Configuration для информирования платформы Spring о том, что это конфигурационный файл, ос­нованный на Java.

После этого для объявления бина Spring и требований DI при­меняется аннотация @Bean.

@Bean

Аннотация @Bean эквивалентна дескриптору <bean>, а имя метода - атрибуту id дескриптора <bean>.

Другие аннотации

@ImportResource(value = "classpath:META-INF/spring/app-context-xml.xml") - для импортирова­ния конфигурации из ХМL-файлов, что означает возможность совместного применения ХМL и Jаvа-классов конфигурации, хотя поступать подобным образом не рекомендуется.

@PropertySource(value = "classpath:message.properties") применяется для загрузки файлов свойств в ApplicationContext и принимает в качестве арrумента местоположение (до­пускается указывать более одного местоположения). В ХМL той же самой цели служит дескриптор <context:property-placeholder>.

@ComponentScan(basePackages = {"com.test"})

@EnableTransactionManagement

@Lazy(value = true)

@DependsOn(value = "messageProvider")

@Qualifier

JSR-330

@Named("messageProvider") - применяется для объявления внедряемого бина (аналогично аннотации @Component или @Service в Spring).

@Inject

@Singleton - стандарте JSR-330 по умолчанию бин является неодиночным, что похоже на область действия на уровне прототипа в Spring. Таким образом, если вы хотите, чтобы в сре­де JSR-330 ваш бин был одиночным, то должны применять аннотацию @Singleton.

Классы 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

определяет 3 типа вызова getМessage(): getMessage(String, Object[], Locale) getMessage(String, Object[] , String, Locale) getMessage(MessageSourceResolvable, Locale)

Реализации: 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.

ApplicationEvent

Событие - это класс, производный от ApplicationEvent, который сам яв­ляется производным от java.util.EventObject. Любой бин может прослу­шивать события, реализовав интерфейс ApplicationListener<T>; при этом AppliсаtionContext автоматически регистрирует любой сконфигурированный бин, который реализует данный интерфейс, в качестве прослушивателя.

Публикация события через ApplicationContext:

ApplicationContext ctx = ...;
ctx.publishEvent(new ApplicationEvent(...));

Resource

В интерфейсе Resource определены десять само­очевидных методов: contentLength(), exists(), getDescription(), getFile(), getFileName(), getURI(), getURL(), isOpen(), isReadble() и lastModified(). В дополнение к этим десяти методам имеется еще один, не столь самоочевидный: createRelative(). Метод createRelative() создает новый экземпляр Resource, используя путь относительно экземпляра, на котором он вызывается.

В большинстве случаев будет применяться одна из встроенных ре­ализаций для доступа к файлу (класс FileSystemResource), пути классов (класс ClassPathResource) или URL-pecypcaм (класс UrlResource).

Environment

Для установки активного профиля необходимо обратиться к интерфейсу Environment. Этот интерфейс представляет собой уровень абстракции, предназна­ченный для инкапсуляции среды выполняющегося приложения Spring. Кроме профилей интерфейс Environment инкапсулирует и другие ключевые порuии информаuии - свойства. Свойства служат для сохранения лежащей в осно­ве приложения конфигурации среды, куда входит местоположение папки приложе­ния, параметры подключения к базе данных и т.д. см. beans profile

АОП

Типы АОП

Различают два типа АОП: статическое и динамическое. При ста­тическом АОП, таком как предоставляемое механизмами связывания во вре­мя компиляции AspectJ, сквозная функциональность применяется к коду на этапе компиляции, и ее нельзя изменить без модификации кода и повторной компиляции.

Концепция

Joiлpoint: Точка соединения - это четко определенная точ­ка во время выполнения приложения. Типовые примеры точек соединения включают обращение к методу, собственно вызов метода (Method Invocation), инициализацию класса и создание экземпляра объекта.

Advice: Фрагмент кода, который должен выполняться в отдельной точке со­единения, представляет собой совет (advice), определенный методом в классе.

Pointcut: Срез (pointcut) - это коллекция точек соединения, которая использу­ется для определения ситуации, когда совет должен быть выполнен.

Aspect: Аспект (aspect) - это комбинация совета и срезов, инкапсулированных в классе.

Weaving: Связывание (weaving) представляет собой процесс вставки аспек­тов в определенную точку внутри кода приложения.

Target: Цель (target) - это объект, поток выполнения которого изменяется ка­ким-то процессом АОП.

Introduction: Введение (introduction) представляет собой процесс, посредством которого можно изменить структуру объекта за счет помещения в него допол­нительных методов или полей.

Spring-AOP-interfaces.png

MethodInvocation

Представляет вызов метода, снабжаемый советом, и с помощью этого объекта мы управляем тем, когда вызову метода разрешено продолжаться.

ProxyFactory

Используется для создания прокси целевого объекта и одновременного его связывания с советом.

Пример:

MessageWriter target = new MessageWriter(); // целевой объект
ProxyFactory pf = new ProxyFactory();
pf.addAdvice(new MessageDecorator()); // установка совета
pf.setTarget(target); // установка целевого объекта
MessageWriter proxy = (MessageWriter) pf.getProxy(); // получение прокси-объекта с советом
proxy.writeMessage(); // вызов метода прокти-объекта

Один и тот же экземпляр ProxyFactory можно применять для создания множес­тва прокси, каждый из которых имеет отличающийся аспект. Чтобы помочь в этом, в ProxyFactory предусмотрены методы removeAdvice() и removeAdvisor(), позволяющие удалять из ProxyFactory любой совет или реализации Advisor, ко­торые ранее были добавлены.

Для проверки, имеет ли ProxyFactory конкретный присоединенный к нему совет, вызовите метод adviceincluded(), передав ему проверяемый объект совета.

При подмешивании (mixin): Вызов setOptimize(true) обеспечивает применение CBLIB, чтобы сработало наследование и подмешивание интерфейса. При использовании setOptimize(false) (по умолчанию) используется JDK для создания прокси и тогда применяется только интерфейс смеси.

setFrozen(true) запрещает смену совета (advice) для оптимизации.

exposeProxy ???

ProxyFactoryBean

В АОП, реализованном платформой Spring, класс ProxyFactoryBean предоставляет декларативный способ кон­фигурирования ApplicationContext (и, следовательно, лежащего в осно­ве BeanFactory) при создании прокси АОП на основе определенных бинов Spring.

Пример декларативного вида для советов:

bean1 - все снабжается советом, т.к. нет никаких срезов.

bean2 - совет снабжается только на метод foo, т.к. есть срез.
<bean id="myBean1" class="MyBean">
  <property name = "dep">
    <ref bean = "myDependencyl "/>
  </property>
</bean>

<bean id="myBean2" class="MyBean">
  <property name="dep">
    <ref bean="myDependency2 "/>
  </property>
</bean>

<bean id="myDependencyl" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="target">
    <ref bean="myDependencyTarget" />
  </property>
  <property name="interceptorNames">
    <list>
      <value>advice</value>
    </list>
  </property>
</bean>

<bean id="myDependency2" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="target">
    <ref bean="myDependencyTarget" />
  </property>
  <property name="interceptorNames">
    <list>
      <value>advisor</value>
    </list>
  </property>
</bean>

<bean id="advice" class="MyAdvice"/>

<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
  <property name="advice">
    <ref bean="advice"/>
  </property>
  <property name="pointcut">
    <bean class="org.springframework.aop.aspectj.AspectJExpressionPointcut">
      <property name="expression ">
        <value>execution(* foo*( .. ))</value>
      </property>
    </bean>
  </property>
</bean>

Пример декларативного вида для введений:

<bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="target">
    <bean class="TargetBean">
      <property name="name">
        <value>Sasha V.</value>
      </property>
    </bean>
  </property>
  <property name="interceptorNames">
    <list>
      <value>advisor</value>
    </list>
  </property>
  <property name="proxyTargetClass">
    <value>true</value>
  </property>
</bean>

<bean id="advisor" class="IsModifiedAdvisor"/>

Advisor

В реализации АОП в Spring аспект представляется экземпляром клacca, который реализует интерфейс Advisor. Платформа Spring предлагает удобные реализации Advisor, которые можно применять в своих приложениях, устраняя необходимость в создании специальных реализаций Advisor. Существуют два подчиненных интер­фейса Advisor: IntroductionAdvisor и PointcutAdvisor.

Если необходим дополнительный кон­троль над созданием Advisor или нужно добавить введение к прокси, создайте реализацию Advisor самостоятельно и используйте метод addAdvisor() класса ProxyFactory.

MethodВeforeAdvice

Совет "перед" (before), можно осущест­ влять специальную обработку перед входом в точку соединения.

void before(Method method, Object(] args, Object target) throws ThrowaЫe

AfterReturningAdvice

Совет "после возврата" (after returning) выполняется после завершения выполнения вызова метода в точке соединения и возврата значения.

Учитывая, что метод уже выполнен, переданные ему аргументы модифицировать невозможно

В совете "после возврата" невозможно модифицировать возвраща­емое значение.

Несмотря на то что совет "после возврата" не позво­ляет изменять возвращаемое значение вызова метода, можно сгенерировать исклю­чение, которое будет передано вверх по стеку вместо возвращаемого значения.

void afterReturning(Object returnValue, Method method, Object[] args,Object target) throws Throwble

AfterAdvice

Совет "после возврата" выполняется только в случае нормального завершения метода, снабженного советом. Однако совет "после" (after(finally)) будет выполняться вне зависимости от ре­зультата метода, снабженного этим советом.

Methodinterceptor

В Spring совет "вокруг" (around) моделируется с исполь­зованием стандарта Альянса АОП для nерехватчика метода.

Интерфейс Methodinterceptor - это стандартный интерфейс Альянса АОП для реализации совета "вокруг" для точек соединения вызовов методов. Object invoke(Methodinvocation invocation) throws Throwable

ThrowsAdvice

Совет "перехват" (throws) выполняется после возврата из вызова метода, но только в случае, если во время вызова было сгенерировано исключе­ние.

Первый метод afterThrowing () в классе принимает единственный аргумент типа Exception. В нем можно указывать любой тип исключения, и этот метод идеально подходит, когда вас не интересует метод, сгенерировавший исключение, или переданные ему ар­гументы.

void afterThrowing(Exception1 ех) throws Throwable

Во втором методе afterThrowing () мы объявили четыре аргумента для ука­зания метода, сгенерировавшего исключение, аргументов, переданных этому ме­тоду, и цели вызова метода. Порядок следования аргументов в этом методе важен, и они должны быть указаны все четыре.

void afterThrowing(Method method, Object[] args, Object target, Exception1 ех) throws Throwable

Exception1 - это конкретный тип исключения и все его подтипы для перехвата.

Spring использует метод, сигнатура которого в наибольшей степени соответствует типу исключения.

В ситуации, когда совет "перехват" имеет дело с двумя методами afterThrowing(), причем оба объявлены с тем самым типом Exception, но один принимает единственный аргумент, а другой - четыре аргумента, платформа Spring вызывает метод afterThrowing() с четырьмя аргументами.

IntroductionInterceptor

Платформа Spring моделирует "введения" (introduction) как специальные типы перехватчиков. Используя перехватчик введения, можно указать реали­зацию методов, которые должны быть введе­ны советом

Pointcut

public interface Pointcut {
  ClassFilter getClassFilter ();
  Method Мatcher getMethodМatcher();
}

В версии Spring 4.0 предлагаются восемь реализаций интерфейса Pointcut:

AnnotationМatchingPointcut - Срез, который ищет специфическую Jаvа­ аннотацию в классе или методе.

AspectJExpressionPointcut - Срез, который использует средство связывания AspectJ для оценки выражения среза, представлен­ ного с помощью синтаксиса AspectJ

ComposablePointcut - применяется для объединения двух и более срезов с помощью таких операций, как union() и intersection()

ControlFlowPointcut - срез, предназначенный для специального случая, кото­рый соответствует всем методам в потоке управле­ния другого метода - т.е . любому методу, который вызван прямо или косвенно в результате выполне­ния другого метода

DynamicMethodМatcherPointcut - служит ба­зовым классом для построения динамических срезов

JdkRegexpMethodPointcut - позволяет оп­ределять срезы с использованием подцержки ре­гулярных выражений JDK 1.4

NameMatchMethodPointcut - срез, который выполняет простое сопоставление со списком имен методов

StaticMethodМatcherPointcut - служит ба­зовым классом для построения статических срезов

Pointcut-hierarchy.png

DefaultPointcutAdvisor

Класс DefaultPointcutAdvisor - это просто PointcutAdvisor для связывания одного Pointcut с одним Advice.

ClassFilter

boolean matches(Class<?> clazz);

MethodМatcher

public interface MethodМatcher {
  boolean matches(Method m, Class<?> targetClass);
  boolean isRuntime();
  boolean matches(Method m, Class<?> targetClass, Object[J args);
}

Перед использованием MethodMatcher платформа Spring вызывает isRuntime() для вы­яснения, является ли MethodМatcher статическим, на что указывает возвращенное значение false, или же динамическим, что отражается значением true.

Для статического среза Spring вызывает метод matches(Method, Class<T>) ин­терфейса MethodMatcher по одному разу для каждого метода целевого объекта, ке­шируя возвращаемое значение для послед у ющих обращений к этому методу.

Для динамических в дополнении в первому вызову с результатом true платформа Spring проводит дальнейшую проверку для каждого вызова метода, используя matches(Method, Class<T>, Obj ect[]).


АОП с аннотациями

Включение АОП с аннотациями в XML

<aop:aspectj-autoproxy/>

имеет атрибут proxy-target-class. По умолчанию он установлен в false, а это означает, что Spring будет создавать стандартные прокси, основанные на интерфейсах, с использованием динами­ческого прокси JDK. В случае установки proxy-target-class в true платфор­ма Spring будет применять библиотеку CGLIВ для создания прокси, которые ос­нованы на классах .

@Aspect

Применяется к классу совместно с @Component, который будет советом, объявляя его классом аспекта.

@Pointcut

Примеры:

@Pointcut("execution(* com..foo*(int)) && args(intValue)")
@Pointcut ( "bean (myDependency*) ")

@Before

Определяет метод совета перед.

@Before("fooExecution(intValue) && inMyDependency()")

@Around

Определяет метод совета вокруг.

@Around("fooExecution(intValue) && inMyDependency()")

JDBC

Настройка конфигурации jdbc в XML:

xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdЬc http://www.springframework.org/schema/jdbc/spring-jdЬc.xsd"

JdbcTemplate

JdbcTemplate - универсальный класс для работы с запросами, отображения из таблиц в коллекции и наоборот.

JdbcDaoSupport

Позволяет упростить формирование DAO формируя ссылку на JdbcTemplate.

DataSource

Предо­ставляет и управляет набором реализаций Connection. Реализация: DriverManagerDataSource Пример конфигурации:

<bean id = "dataSource" class = "org.springframework.jdЬc.datasource.DriverManagerDataSource"
 p:driverClassName="${jdЬc.driverClassName}"
 p:url="$ { jdbc. url}"
 p:username = "${jdЬc.username}"
 p:password = "${jdbc.password}"/>
<context:property-placeholder location = "classpath:META-INF/config/jdbc.properties"/>

jdbc.properties:

jdbc.driverClassName=com.mysql.jdЬc.Driver
jdbc.url = jdbc:mysql://localhost:3306/prospring4 сhб
jdbc.username = prospring4
jdЬc.password=prospring4

JNDI до версии 2.5:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"
 p:jndiName = "java:comp/env/jdbc/prospring4ch6"/>

JNDI с версии 2.5:

<beans xmlns = "http://www.springframework.org/schema/beans"
 xmlns:xsi = "http://www.wЗ.org/2001/XMLSchema-instance"
 xmlns:jee = "http://www.springframework.org/schema/jee"300
 xsi:schemaLocation = "http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/jee
 http://www.springframework.org/schema/jee/spring-jee.xsd">
  <jee:jndi-lookup jndi-name = "java:comp/env/jdЬc/prospring4ch6"/>
</beans>

Ссыпка на ресурс в файле описателя приложения:

<root-node>
 <resource-ref>
  <res-ref-name>jdbc/prospring4ch6</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
 </resource-ref>
</root-node>

Например, он становится <web-app> в описателе веб-развертывания (WEB-INF /web. xrnl), если приложение представляет собой веб-модуль.

NamedParameterJdbcTemplate

Пример применения именованных запросов:

private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
... {
  String sql = "select last_name from contact where id = :contactId";
  Map<String, Object> namedParameters = new HashMap<String, Object>();
  namedParameters.put("contactId", id);
  return namedParameterJdbcTemplate.queryForObject(sql, namedParameters, String.class);
}

RowМapper<T>

Интерфейс для простого способа отобра­жения результирующего набора JDBC на объекты POJO.

private static final class ContactMapper implements RowMapper<Contact> {
  public Contact mapRow(ResultSet rs, int rowNum) throws SQLException {
    Contact contact = new Contact();
    contact.setid(rs.getLong("id"));
    contact.setFirstName(rs.getString("first_name"));
    contact.setLastName(rs.getString("last_name") );
    contact.setBirthDate(rs.getDate("Ьirth_date") );
    return contact;
  }
}

Объявление класса ContactMapper как статического внутреннего класса позволяет совместно использовать RowMapper<T> множеством методов поиска.

Использование в DAO

String sql = "select id, first_ name, last_ name, Ьirth_date from contact";
return namedParameterJdЬcTemplate.query(sql, new ContactMapper());


При работе с Java 8 вместо создания класса ContactMapper, как было показано ранее, можно применить лямбда-выражение: @Override

public List<Contact> findAll() {
  String sql = "select id, first_name, last_name, Ьirth date from contact";
  return namedParameterJdbcTemplate.query(sql, (rs, rowNum) -> {
    Contact contact = new Contact();
    contact.setid(rs.getLong("id"));
    contact.setFirstName(rs.getString("first_name"));
    contact.setLastName(rs.getString("last_name"));
    contact.setBirthDate(rs.getDate("Ьirth_date"));
    return contact;
  });
}

такое возможно из-за того, что в интерфейсе RowМapper описан 1 метод с 2 параметрами ResultSet rs, int rowNum.

RowMapper<T> подходит только для отображения строки на одиночный объект предметной области.

ResultSetExtractor

Для получения связанных объектов реализуем метод ex­tractData() для трансформации результирующего набора в список объектов.

public List<?> extractData(ResultSet rs) throws SQLException,DataAccessException

или лямба выражение

return namedParameterJdbcTemplate.query(sql, (ResultSet rs) -> (
 ...
 return ArrayList ...;
});

jdbc embedded

Пример встроенной БД:

<jdbc:emЬedded-database id="dataSource" type="H2">
 <jdbc:script location="classpath:META-INF/sql/schema.sql"/>
 <jdbc:script location="classpath:META-INF/sql/test-data.sql"/>
</jdЬc:emЬedded-database>

Важен порядок следования:

1. Схема (DDL (Data Definition Language)) - schema.sql,

2. данные (DML (Data Manipulation Language) - test-data.sql.

В атрибуте type задается тип используемой встроенной базы данных. В версии Spring 4.0 поддерживаются типы HSQL (стандартный), Н2 и DERBY.

Вместо указания type и embedded-database просто используйте initialize-database, и сценарии будут выполняться в отношении заданного источника данных, как если бы речь шла о встроенной базе данных.