1 2 |
<bean id="messageService" class="asos.springapp1.MessageServiceMock"/> <bean id="processor" class="asos.springapp1.MessageProcessor" autowire="byName"> |
V xml nie je explicitne uvedená komponenta, ktorá má byť injektovaná ale vyhladanie vhodnej komonenty pre DI je prenechané na IoC kontainer. Atribút autowire udáva podľa čoho má vhodnú komponentu vyhľadať:
namiesto autowire atribútu v XML použijeme anotáciu @Autowired v kóde. Aby však kontainer vedel použiť anotácie treba do XML pridať element <context:annotation-config/>
Pozn. Pri vytváraní spring-config treba pridat knižnicu context
1 2 3 |
<context:annotation-config/> <bean id="service" class="asos.springapp1.MessageServiceMock"/> <bean id="processor" class="asos.springapp1.MessageProcessor"/> |
Anotáciu @Autowired môžeme použiť pre anotovanie construktora aj setter-metódy
1 2 3 4 |
@Autowired public void setMessageService(MessageServiceIfc messageService) { this.messageService = messageService; } |
Pre povinné referencie môžeme použiť aj anotáciu @Required Pre nepovinné referencie môžeme použiť @Autowired(required = false))
V xml netreba uvádzať ani komponenty. Stačí tam dať element
1 |
<context:component-scan base-package="edu"/> |
ktorým kontaineru povieme v akom baliku má hladať komponenty. Komponenty musia byť anotované @Component prípadne. @Repository, @Service, @Controller
umožňuje konfiguráciu kontainera úplne bez XML. Namiesto XML je konfigurácia definovaná pomocou špeciálnej Factory triedy anotovanej @Configuration
Táto trieda implementuje factory metódy ktoré volá kontainer aby vytvoril komponenty. Faktory metódy sú anotované @Bean
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Configuration //@ComponentScan(basePackages = "asos") public class DemoAppConfig { @Bean(name="myMessageBean") public MessageServiceIfc serviceFactory() { return new MessageServiceMock(); } @Bean(name="myProcessor") public MessageProcessor processorFactory(@Named("myMessageBean") MessageService ms) { return new MessageProcessor(ms); } } |
Všimnite si, že myFactory volá konštruktor MessageProcessor s parametrom – teda využíva constructor-based DI. Pozn. (Rovnako je možné použiť aj setter-based DI – úloha na cvičenie) Samotná komponenta nemusí obsahovať žiadne anotácie (nemá ani žiadne iné závislosti na sprigu, spring anotácie sú odkomentované )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package asos; //@Named("myProcessor") public class MessageProcessor { //@Autowired private MessageServiceIfc messageService; public MessageProcessor(MessageService messageService) { this.messageService = messageService; } public void processMessage() { System.out.println(messageService.getMessage()); } } |
Keďže je teraz konfigurácia kontainera definovaná Factory-triedou (namiesto xml dokumentu) musíme pre inicializáciu aplikácie použiť AnnotationConfigApplicationContext (namiesto ClassPathXmlApplicationContext).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class DemoApplication { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(DemoAppConfig.class); // = new ClassPathXmlApplicationContext(new String[]{"beans.xml"}); // retrieve configured instance MessageProcessor m = context.getBean("myProcessor", MessageProcessor.class); m.processMessage(); } } |
http://www.tutorialspoint.com/spring/aop_with_spring.htm
The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Dependency Injection helps you decouple your application objects from each other and AOP helps you decouple cross-cutting concerns from the objects that they affect. AOP islike triggers.
execution ( modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern? )
Pozn. Jazyk pre popis pointcut pattern je definovaný špecifikáciou AspectJ.
Do maven konfigurácie treba okrem spring doplniť aj dependency pre AOP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.1.RELEASE</version> </dependency> <!--AOP--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.9</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.8.9</version> </dependency> </dependencies> |
XML konfigurácia kontainera (beans.xml) musí importovať taglib http://www.springframework.org/schema/aop. Pri generovani konfigurácie pomocou netbeans wizardu to dosiahneme začeknutím aop-supportu.
ilustruje použitie rôznych typov advice a pointcut výrazov. Jednoduchá aplikácia pozostáva z jednej komponenty s niekoľkými metódami, ktoré sú volané z hlavného programu.
implmentuje funkcionalitu aplikácie
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class MyOperationBean { public void msg(String message) { System.out.println("msg method invoked: " + message); try { Thread.sleep(1500); } catch (InterruptedException ex) { Logger.getLogger(MyOperationBean.class.getName()).log(Level.SEVERE, null, ex); } } public int m() { System.out.println("m method invoked"); return 2; } public int k() { System.out.println("k method invoked"); return 3; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class TestMain { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("myBeanConfig.xml"); MyOperationBean bean = (MyOperationBean) context.getBean("opBean"); System.out.println("calling m..."); bean.m(); System.out.println("calling k..."); bean.k(); System.out.println("calling msg..."); bean.msg("hello"); } } |
zatiaľ bez použitia AOP
1 2 3 4 5 6 7 8 9 |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd "> <bean id="opBean" class="asos.aopdemo.MyOperationBean"></bean> </beans> |
Funkcionalita aspektu je implementovaná v samostatnej komonente.
MyAspectBean implementuje ukážky rôznych typov advice metód:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public class MyAspectBean { public void myBeforeAdvice(JoinPoint jp) { System.out.println("\tmy before advice"); System.out.println("\tMethod Signature: " + jp.getSignature()); } /* vypise navratovu hodnotu */ public void myReturnAdvice(JoinPoint jp, Object result) { System.out.println("\tmy return advice"); System.out.println("\tResult in advice: " + result); } /* zisti a vypise dobu vykonavania volanej metody */ public Object myAroundAdvice(ProceedingJoinPoint call, String message) throws Throwable { System.out.println("\tmy around advice " + message); StopWatch clock = new StopWatch("\tProfiling"); try { clock.start(call.toShortString()); return call.proceed(); // mozeme dokonca zmenit aj argumenty alebo navratovu hodnotu // Object[] par = {"ahoj"}; // return call.proceed(par); } finally { clock.stop(); System.out.println(clock.prettyPrint()); } } } |
Modifikáciou konfigurácie môžeme teraz definovať v aplikácii rôzne pointcut-y a aktivovať pre ne jednotlivé advice
Before advice pre všetky metódy triedy MyOperationBean s menom začínajúcim na m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd "> <bean id="opBean" class="asos.aopdemo.MyOperationBean"></bean> <bean id="trackAspect" class="asos.aopdemo.MyAspectBean"></bean> <aop:config> <aop:aspect id="myaspect" ref="trackAspect" > <!-- @Before --> <aop:pointcut id="pointCutBefore" expression="execution(* asos.aopdemo.MyOperationBean.m*(..))" /> <aop:before method="myBeforeAdvice" pointcut-ref="pointCutBefore" /> </aop:aspect> </aop:config> </beans> |
After returning advice pre všetky metódy MyOperationBean
1 2 3 |
<!-- @AfterReturning --> <aop:pointcut id="pointCutRet" expression="execution(* asos.aopdemo.MyOperationBean.*(..))" /> <aop:after-returning method="myReturnAdvice" returning="result" pointcut-ref="pointCutRet" /> |
Around advice pre metódu MyOperationBean.msg
1 2 3 |
<!-- @Around --> <aop:pointcut id="pointCutAround" expression="execution(* asos.aopdemo.MyOperationBean.msg(String)) and args(message)" /> <aop:around method="myAroundAdvice" pointcut-ref="pointCutAround"/> |