72
Spring Training 17/09/2007

Spring Training 17/09/2007. 2 Dependency Injection

Embed Size (px)

Citation preview

Spring Training

17/09/2007

2

Dependency Injection

3

How Do Factories work?

• Factories solve a common problem in software engineering: hiding the complexity of creating and configuring objects.

• example of a factory object in the Java SDK is the javax.net.SocketFactory class

• The Spring Framework Core Container supports both factory methods and factory objects as an alternative to creating new beans.

javax.net.SocketFactory factory = javax.net.SocketFactory.getDefault();

java.net.Socket socket = factory.createSocket("localhost", 80);

4

Introducing the BeanFactory

• The Spring Framework Core Container is also a factory object with configuration parameters and factory operations to support IoC.

• The operations of the Core Container are defined in the org.springframework.beans.factory.BeanFactory interface

5

Setter injection and Constructor Injection

package com.virtusa.spring.firstexample.play; public class Player { private String fullName; private int ranking; Player(){}//for empty constructor need for bean-config Player(String fullName, int ranking){ this.fullName = fullName; this.ranking = ranking; } public void setFullName(String fullName) { this.fullName = fullName; } public void setRanking(int ranking) { this.ranking = ranking; } public String getFullName() { return fullName; } public int getRanking() { return ranking; } }

6

bean-config file

<?xml version="1.0" encoding="UTF-8"?> <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-2.0.xsd"> <bean id="ojitha" class="com.virtusa.spring.firstexample.play.Player"> <property name="fullName" ref="ok"></property> <property name="ranking" value="1"></property> </bean> <bean id="ok" class="java.lang.String"> <constructor-arg value="Ojitha Kumanayaka"></constructor-arg> </bean> <bean id="ruwan" class="com.virtusa.spring.firstexample.play.Player"> <constructor-arg value="Ruwan W."></constructor-arg> <constructor-arg value="1"></constructor-arg> </bean> </beans>

7

Test with JUnitpackage com.virtusa.spring.firstexample.play; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import junit.framework.TestCase; public class TestPlayer extends TestCase { private BeanFactory beanFactory; public void setUp(){ beanFactory = new XmlBeanFactory( new ClassPathResource("bean-config.xml")); } public void testPlayer() { String targetFullName ="Ojitha Kumanayaka"; int targetRanking = 1; Player player = (Player)beanFactory.getBean("ojitha"); assertEquals(targetFullName, player.getFullName()); assertEquals(targetRanking,player.getRanking()); } public void testPlayerStringInt() { String targetFullName="Ruwan W."; int targetRanking = 1; Player player = (Player)beanFactory.getBean("ruwan"); assertEquals(targetFullName, player.getFullName()); assertEquals(targetRanking,player.getRanking()); } }

8

Constructor Overload

Player(String fullName, Integer id){ this.fullName = fullName; this.id = id; } Player(String fullName, int ranking){ this.fullName = fullName; this.ranking = ranking; }

public void testPlayerStringInteger(){ String targetFullName="Harsha W."; Integer targetId = new Integer(1); Player player = (Player)beanFactory.getBean("harsha"); assertEquals(targetFullName, player.getFullName()); assertEquals(targetId, player.getId()); }

Player Bean

<bean id="harsha" class="com.virtusa.spring.firstexample.play.Player"> <constructor-arg value="Harsha W."></constructor-arg> <constructor-arg value="1"></constructor-arg> </bean>

TestPlayer

9

Constructor Overload

Player(String fullName, Integer id){ this.fullName = fullName; this.id = id; } Player(String fullName, int ranking){ this.fullName = fullName; this.ranking = ranking; }

public void testPlayerStringInteger(){ String targetFullName="Harsha W."; Integer targetId = new Integer(1); Player player = (Player)beanFactory.getBean("harsha"); assertEquals(targetFullName, player.getFullName()); assertEquals(targetId,player.getId()); }

Player Bean

<bean id="ruwan" class="com.virtusa.spring.firstexample.play.Player"> <constructor-arg value="Ruwan W."></constructor-arg> <constructor-arg value="1" type="int"></constructor-arg> </bean> <bean id="harsha" class="com.virtusa.spring.firstexample.play.Player"> <constructor-arg value="Harsha W."></constructor-arg> <constructor-arg value="1" type="java.lang.Integer"></constructor-arg> </bean>

TestPlayer

10

Combine Constructor and setter

Player(String fullName, Integer id){ this.fullName = fullName; this.id = id; } public void setRanking(int ranking) { this.ranking = ranking; }

public void testPlayerStringInteger(){ String targetFullName="Harsha W."; Integer targetId = new Integer(1); int targetRanking = 1; Player player = (Player)beanFactory.getBean("harsha"); assertEquals(targetFullName, player.getFullName()); assertEquals(targetId, player.getId()); assertEquals(targetRanking, player.getRanking()); }

Player Bean

<bean id="harsha" class="com.virtusa.spring.firstexample.play.Player">

<constructor-arg value="Harsha W."></constructor-arg> <constructor-arg value="1" type="java.lang.Integer"></constructor-arg> <property name="ranking" value="1"></property> </bean>

TestPlayer

FirstExample-1.zip

11

Setter or constructor ?

• Setter injection is more popular because it’s more self-documenting and isn’t affected by circular dependency problems, which may occur if you use constructor injection.

• Setter injection leaves beans in an indeterminate state, something you can avoid with constructor injection

12

Inner bean (anonymous)

• The container supports inner bean definition, also called anonymous bean definitions since they cannot be referenced by other bean definitions.

• Inner bean definitions are useful for making the configuration more readable and to avoid exposing beans that are used in only one place.

13

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" …………………………………

………………………………… <bean id="ojitha" class="com.virtusa.spring.firstexample.play.Player"> <property name="fullName" ref="ok"></property> <property name="ranking" value="1"></property> </bean> <bean id="ok" class="java.lang.String"> <constructor-arg value="Ojitha Kumanayaka"></constructor-arg> </bean>

………………………………… ………………………………… </beans>

<bean id="ojitha" class="com.virtusa.spring.firstexample.play.Player"> <property name="fullName"> <bean class="java.lang.String"> <constructor-arg value="Ojitha Kumanayaka"></constructor-arg> </bean> </property> <property name="ranking" value="1"></property> </bean>

FirstExample-2.zip

14

The <value> Element

15

The <ref> Element

16

The <list> Element

17

The <map> Element

18

19

The <prop> Elements

20

The <set> Element

21

Bean life-cycle

• The container creates and configures a bean based on its bean definition, which provides a single point to configure the life cycle of the bean.

• Along with dependency injection, the container also provides life-cycle options that address the following• Scope

• Initialization

• Destruction

22

Scope

• The scope of a bean defines the behavior of the container when a bean is requested, either via dependency injection or dependency lookup.

• By default, beans are singleton, which means they are created and configured once and stored in a cache. When a singleton bean is requested, the container returns the instance from the cache.

• Optionally, beans can be prototype, which means they are created and configured by the container on each request. When a prototype bean is requested, the container creates and configures a new bean and doesn’t keep track of it.

23

Initialization

• The initialization of beans is available for singleton and prototype beans.

• The container can invoke a method on a bean if it implements a specific interface that is part of the• Spring Framework API or

• if a custom initialization method has been configured on the bean definition.

• This is an optional step in the life cycle of a bean.

24

Destruction

• The destruction of beans is available only for singleton beans.

• The container can invoke a method on a bean • if it implements a specific interface that is part of the Spring

Framework API or

• if a custom destroy method has been configured on the bean definition.

• This is an optional step in the life cycle of a singleton bean.

25

Singleton

• Without extra configuration on the bean definition, beans are singleton

• A singleton bean may be used by multiple threads running concurrently, meaning its operations must be implemented in a thread-safe way.

• The execution of the bean life-cycle process by the container is guaranteed to be thread-safe, so operations that are executed during this process are not subject to thread-safety issues.

• Once the life-cycle process of the container is over, all operations that are allowed on singleton beans must happen in a thread-safe way.

• By default, the BeanFactory will not preinstantiate singletons, but will instead create each singleton bean when it’s first requested

PrimeNumber-1.zip

26

Using prototypes

• Prototype beans typically have internal state that is related to a single execution of a business process.

• Every execution of the business process requires a new bean, and executions that run concurrently cannot share the same bean.

• To configure a bean definition as a prototype, set the singleton attribute of the <bean> element to false

<?xml version="1.0" encoding="UTF-8"?> <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-2.0.xsd"> <bean id="primeIterator" class="com.virtusa.spring.prime.PrimeIterator"

scope="prototype"> <property name="start" value="1000"/> </bean> </beans>

27

• the BeanFactory will not preinstantiate singletons, but will instead create each singleton bean when it’s first requested

• In contrast, the ApplicationContext will preinstantiate singleton beans

• Prototype beans are not preinstantiated by the BeanFactory or ApplicationContext container

28

Bean Initialization

• The container can optionally initialize beans, either • via an interface that is implemented by beans or

• via a custom initialization method

• Initialization step can be used to check the internal state of beans

• The container will initialize any bean that implements the org.springframework.beans.factory.InitializingBean interface

29

Initialize via interface

import org.springframework.beans.factory.InitializingBean; public class Player implements InitializingBean { private String fullName; private int ranking; private Integer id; Player() { }// for empty constructor need for bean-config Player(String fullName, Integer id) { this.fullName = fullName; this.id = id; } public void afterPropertiesSet() throws Exception { if (this.ranking == 0) throw new RequiredPropertyNotSetException("ranking required..."); }

SecondExample-1.zip

30

Using Custom Initialization Methods

public class PrimeIterator { private int start; private int current; private int[] primesFound; public void initialize() throws Exception{ this.start=2; this.current=0; primesFound = new int[] { 2, 3 }; } <?xml version="1.0" encoding="UTF-8"?> <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-2.0.xsd"> <bean id="primeIterator" class="com.virtusa.spring.prime.PrimeIterator" scope="prototype" init-method="initialize"> <property name="start" value="1000"/> </bean> </beans>

31

Using Custom Initialization Methods

• The init-method attribute takes the method name of the custom initialization method.

• The container requires that custom initialization methods have no arguments.

• They can throw exceptions that are handled in the same way as those thrown by the afterPropertiesSet() method and can return values, but these are ignored by the container.

• We recommend that you use the custom initialization method strategy as much as possible, since it avoids coupling application code to the Spring Framework API.

32

Bean Destruction

• Prototype objects are created by the container, returned, and forgotten about.

• The container does not keep track of prototype beans.

• The life cycle is restarted for a prototype every time a new object is created.

• In contrast, singleton instances are stored in a cache and can be destroyed when the container is closed.

• The destruction step is useful for cleaning up resources when the application stops.

• Just like the initialization step, the destruction step can be configured in two ways: • through an interface that is implemented by beans or• through a custom destruction method.

33

Using the DisposableBean Interface

• Does not require special configuration, as the container will recognize that the class implements the DisposableBean interface

public class Player implements InitializingBean, DisposableBean { private String fullName; private int ranking; private Integer id; public void destroy() throws Exception { this.fullName = null; }

SecondExample-2.zip

@Test public void destroy(){ Player player = (Player)beanFactory.getBean("ojitha"); beanFactory.destroySingletons(); assertNull(player.getFullName()); }

34

Using a Custom Destroy Method

<?xml version="1.0" encoding="UTF-8"?> <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-2.0.xsd"> <bean id="primeIterator" class="com.virtusa.spring.prime.PrimeIterator" init-method="initialize" scope="singleton" destroy-method="close"> <property name="start" value="1000"/> </bean> </beans>

public class PrimeIterator { private int start; private int current; private int[] primesFound; public boolean close = false; public void close() throws Exception { this.primesFound = null; close = true; }

PrimeNumber-2.zip

public void testPreInstantiateSingletons() { ConfigurableListableBeanFactory beanFactory =

new XmlBeanFactory(new ClassPathResource( "bean-config.xml")); PrimeIterator primeNumber1 =

(PrimeIterator) beanFactory .getBean("primeIterator"); beanFactory.destroySingletons(); assertTrue(primeNumber1.close); }

35

Using Factory Methods and Factory Objectsin the Container

• Factories that come in two forms: • factory methods and• factory objects.

• The container supports both factory types as an alternative to creating new beans.

• The products of factories are used by the container as beans, which means the container must know how to get objects from the factories.

• The beans that are returned by factory methods and factory object methods go through the entire bean life cycle• Singleton/prototype configuration• Setter injections• Initialization methods• Destroy methods, if configured as singleton

• When the factory object bean definition is configured as a prototype, each bean definition that calls one of its methods will trigger the creation of a new factory object bean that will be used only for that method invocation

36

Implementing Factory Methods

<?xml version="1.0" encoding="UTF-8"?> <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-2.0.xsd"> <bean id="pattern" class="java.util.regex.Pattern" factory-method="compile"> <constructor-arg value="abc"/> </bean> </beans>

@Test public void match() { Pattern pattern = (Pattern)beanFactory.getBean("pattern"); Matcher matcher = pattern.matcher("abc abc abc"); int matchCount = 0; while (matcher.find()) { matchCount++; } assertEquals(3, matchCount); } Factories-1.zip

37

Implementing Factory Objects

<bean id="pattern" class="java.util.regex.Pattern" factory-method="compile"> <constructor-arg value="abc" /> </bean> <!-- Factory Object --> <bean id="socketFactory" class="javax.net.SocketFactory" factory-method="getDefault"> </bean> <bean id="localhost" factory-bean="socketFactory" factory-method="createSocket"> <constructor-arg value="localhost" /> <constructor-arg value="8080" /> </bean>

@Test public void connectToSocket(){ java.net.Socket localhost = (java.net.Socket)beanFactory.getBean("localhost"); assertTrue(localhost.isConnected()); try { localhost.close(); assertTrue(localhost.isClosed()); } catch (IOException e) { e.printStackTrace(); } }

Factories-1.zip

38

PropertyEditor

• The bean factory uses PropertyEditors for converting the String values in XML files to the destination type of properties and constructor arguments.

• The java.beans.PropertyEditor interface, which is part of the Java Software Development Kit (SDK), handles the conversion of Strings to a specific type and back.

PropertyEditor.zip

39

ApplicationContext

• The ApplicationContext interface inherits all the capabilities of the BeanFactory interface, including • dependency lookup, • dependency injection, and • support for factories and • PropertyEditors.

• The ApplicationContext automates functionalities that are offered by BeanFactory; for example, it automatically preinstantiates singletons and automatically detects beans that implement specific interfaces in the container.

• The most commonly used feature of the ApplicationContext is its generic representation of resources.

• Resources can reside on the • file system (file:wordlist.txt), • in the classpath (classpath:wordlist.txt), • on a web server accessible through a URL

(http://localhost/wordlist.txt), or • inside a deployed WAR application

40

Representing Resources

• A resource location without a prefix will be loaded from the default location, which depends on the type of ApplicationContext being used

• There are three possible types:• ClassPathXmlApplicationContext: Reads resources from

the classpath by default.• FileSystemXmlApplicationContext: Reads resources from

the file system by default.• XmlWebApplicationContext: Reads resources from the

ServletContext object by default.

• Every time you set a bean property that has the org.springframework.core.io.Resource interface as its type, you can specify a string location that will be converted by the ApplicationContext

41

Creating ApplicationContext Objects

• The three most common ways of creating ApplicationContext objects are as follows:• Creating an ApplicationContext in Java code

• Creating an ApplicationContext in an integration test

• Creating an ApplicationContext in a web application

• The ApplicationContext allows you to load multiple XML files that will be merged into a set of bean definitions

• You should configure the modules of your applications in separate configuration files and load them together in one ApplicationContext.

• This will keep your configuration files small enough to manage conveniently.

42

Using the Container As a Deployment Model

• The Spring Framework offers support to deploy applications in these deployment environments:• Servlet containers: Tomcat, Jetty, and Resin

• Application servers: BEA WebLogic, IBM WebSphere, and JBoss

• Portlet servers: JetSpeed 2 and Pluto

• Thin clients: Java desktop applications that call remote services over a network

• Thick clients: Java desktop applications that directly connect to a database

• Messaging: Applications that connect to message queues and handle incoming messages

43

AOP

• Any functionality that exists in an application, but cannot be added in a desirable way is called a cross-cutting concern

• The field in computer science that deals with cross-cutting concerns is called aspect-oriented programming (AOP)

• It deals with the functionality in applications that cannot be efficiently implemented with pure object-oriented techniques.

• It deals with the functionality in applications that cannot be efficiently implemented with pure object-oriented techniques.

• It deals with the functionality in applications that cannot be efficiently implemented with pure object-oriented techniques.

44

Implementing Cross-Cutting Concerns

• Advice• In AOP jargon, the implementation of a cross-cutting concern is called

an advice.• The advice class is written and compiled once—it’s a regular Java class

—and can be reused many times, meaning it needs to be tested only once.

• Proxy object• Proxy objects are created at runtime by ProxyFactoryBean; you don’t

need to write any code to create them.• All public methods on the target object are available on the proxy

object, and you can decorate any of these methods with advice.• Spring AOP supports two proxy types:

• Java Development Kit (JDK) proxies– specify interface names in the ProxyFactoryBean

configuration• Bytecode proxies

– protected methods on target objects can be called on proxy objects in Spring AOP 2.0, and these methods can be decorated with advice.

– final classes and methods cannot be proxied, which is the sole limitation of bytecode-generated proxy objects.

45

JDK proxy <bean id="seller" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <bean class="com.virtusa.spring.sale.RetailSeller"> <property name="sale" ref="newSale"/> </bean> </property> <!-- JDK proxy --> <property name="proxyInterfaces"> <list> <value>com.virtusa.spring.sale.Seller</value> </list> </property> <property name="interceptorNames"> <list> <idref bean="textMessageSendingAdvice" /> </list> </property> </bean> <bean id="textMessageSendingAdvice" class="com.virtusa.spring.inform.TextMessageSendingAdvice"> <property name="messageSender" ref="messageSender" /> </bean> <bean id="messageSender" class="com.virtusa.spring.inform.TextMessageSender"> </bean> <bean id="newSale" class="com.virtusa.spring.sale.NewSale"> </bean>

Sales-1.zip

46

Seller

package com.virtusa.spring.sale; public interface Seller { public void setSale(Sale sale); public Sale getSale(); }

package com.virtusa.spring.sale; public class RetailSeller implements Seller { private Sale sale; public void setSale(Sale sale){ this.sale = sale; } public Sale getSale(){ return this.sale; } }

47

textMessageSendAdvice

package com.virtusa.spring.inform; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; import com.virtusa.spring.sale.Sale; public class TextMessageSendingAdvice implements AfterReturningAdvice{ private MessageSender messageSender; public void setMessageSender(MessageSender messageSender) { this.messageSender = messageSender; } public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { Sale sale = (Sale) returnValue; this.messageSender.notifyEndOfSale(sale); } }

48

newSale

package com.virtusa.spring.sale; public interface Sale { public int getOrderId(); }

package com.virtusa.spring.sale; public class NewSale implements Sale { private int orderId=0; public int getOrderId() { return ++orderId; } }

49

messageSender

package com.virtusa.spring.inform; import com.virtusa.spring.sale.Sale; public interface MessageSender { public void notifyEndOfSale(Sale sale); }

package com.virtusa.spring.inform; import com.virtusa.spring.sale.Sale; public class TextMessageSender implements MessageSender { public void notifyEndOfSale(Sale sale) { System.out.println("Advice"); System.out.println("======"); System.out.println("order id: "+sale.getOrderId()); } }

50

Bytecode proxy

<bean id="seller" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <bean class="com.virtusa.spring.sale.RetailSeller"> <property name="sale" ref="newSale"/> </bean> </property> <!-- JDK proxy <property name="proxyInterfaces"> <list> <value>com.virtusa.spring.sale.Seller</value> </list> </property> --> <property name="interceptorNames"> <list> <idref bean="textMessageSendingAdvice" /> </list> </property> </bean> <bean id="textMessageSendingAdvice" class="com.virtusa.spring.inform.TextMessageSendingAdvice"> <property name="messageSender" ref="messageSender" /> </bean> <bean id="messageSender" class="com.virtusa.spring.inform.TextMessageSender"> </bean> <bean id="newSale" class="com.virtusa.spring.sale.NewSale"> </bean>

Sales-2.zip

51

Filtering Methods

• AOP frameworks allow you to define which advice is applied to which methods

• Specifying the advice and method involves using what AOP terms join points and pointcuts

• Spring AOP supports only method invocations as join points.

• A pointcut selects zero or more join points on the target object

52

Point cut classes

• Spring AOP has a number of pointcut classes you can use to select join points:• org.springframwork.aop.support.NameMatchMethodPoint

cut: Selects join points based on method names. This class matches method names using an Ant-style wildcard notation

• org.springframwork.aop.support.JdkRegexpMethodPointcut: Selects join points based on method names. This class matches method names using regular expressions and works only with Java 1.4 and newer because it uses the java.util.regexp package.

• org.springframwork.aop.support.Perl5RegexpMethodPointcut: Selects join points based on method names. This class matches method names using regular expressions and uses the Jakarta ORO open source regular expression library; thus, it supports Java 1.3.

• When using the regular expression–based pointcut classes to match method names, the package name, class name, or method name can be matched, offering a more powerful selection mechanism.

53

NameMatchMethodPointcut <bean id="sendTextMessageWhenSell" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="pointcut" ref="sellingMethodPointcut" /> <property name="advice" ref="textMessageSendingAdvice" /> </bean> <bean id="sellingMethodPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut"> <property name="mappedName" value="getSale" /> </bean> <bean id="seller" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <bean class="com.virtusa.spring.sale.RetailSeller"> <property name="sale" ref="newSale" /> </bean> </property> <property name="interceptorNames"> <list> <value>sendTextMessageWhenSell</value> </list> </property> </bean>

Sales-3.zip

54

JdkRegexpMethodPointcut

• Here the pattern property has been set to a regular expression that should match any method called getSale() on any class.

<bean id="sendTextMessageWhenSell" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="pointcut" ref="sellingMethodPointcut" /> <property name="advice" ref="textMessageSendingAdvice" /> </bean> <bean id="sellingMethodPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value=".*getSale"/> </bean>

Sales-4.zip

55

Adding Advisors

• Pointcuts select zero or more join points

• You need to use them in combination with an advice to define to which methods the advice applies

• An advisor takes a pointcut and an advice object and is passed to ProxyFactoryBean

• Methods on proxy objects can have more than one advisor assigned to them. In this case, the order of execution is defined by the order in the XML configuration file

• To control the proper ordering of multiple advisors, Spring AOP uses an advisor chain to execute all configured advisors sequentially.

56

Using PointcutAdvisors

• Spring AOP provides convenience classes for the pointcut classes. These classes turn pointcut classes into advisors. Three classes are available:• org.springframework.aop.support.NameMatchMethodPointcutAdviso

r

• org.springframework.aop.support.JdkRegExpMethodPointcutAdvisor

• org.springframework.aop.support.Perl5RegExpMethodPointcutAdvisor

• These convenience classes inherit the properties defined in the pointcut class they extend and add the advice property

• You should use these classes instead of a separate pointcut and an advisor class to reduce the number of lines in the XML configuration files

57

NameMatchMethodPointcutAdvisor

• So, what happens when an advice is passed to ProxyFactoryBean without an advisor?• Spring AOP uses an advisor for the advice that matches all methods

on the target object. • As a result, an advice that is configured without an advisor will be

applied to all methods of the target object

<bean id="sendTextMessageWhenSell" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name="mappedName" value="getSale"/> <property name="advice" ref="textMessageSendingAdvice" /> </bean> <bean id="seller" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <bean class="com.virtusa.spring.sale.RetailSeller"> <property name="sale" ref="newSale" /> </bean> </property> <property name="interceptorNames"> <list> <value>sendTextMessageWhenSell</value> </list> </property> </bean>

Sales-5.zip

58

Selecting Advice Types

1.Around advice:• Controls the execution of a join point. • This type is ideal for advice that needs to control the execution of

the method on the target object.2.Before advice:

• This Is executed before the execution of a join point. • This type is ideal for advice that needs to performan action before

the execution of the method on the target object.3.After advice:

• This Is executed after the execution of a join point. • This type is ideal for advice that needs to perform an action after

the execution of the method on the target object.4.Throws advice:

• This Is executed after the execution of a join point if an exception is thrown.

• This type is ideal for advice that needs to performan action when the execution of the method on the target object has thrown an exception.

59

Around Advice (Method interceptor)

• The around advice type (also called a method interceptor) controls the flow of method invocations on target objects.

• This advice type is ideal for cross-cutting concerns that need to control the method invocation.

• It is called before the method on the target object is executed and exits after this method returns.

• Around advice classes can access the arguments passed to the method on the proxy object by calling the MethodInvocation.getArguments() method

60

Method interceptor definition

<bean id="profilingAdvice" class="com.virtusa.spring.profiling.SimpleProfiling" /> <bean id="seller" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <bean class="com.virtusa.spring.sale.RetailSeller"> <property name="sale" ref="newSale" /> </bean> </property> <property name="interceptorNames"> <list> <idref bean="sendTextMessageWhenSell"/> <idref bean="profilingAdvice"/> </list> </property> </bean>

Sales-6.zip

61

Simple profiling class of MethodInterceptor

package com.virtusa.spring.profiling; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.util.StopWatch; public class SimpleProfiling implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { StopWatch stopWatch = new StopWatch(); stopWatch.start(); try{ return invocation.proceed(); } finally{ stopWatch.stop(); System.out.println(stopWatch.prettyPrint()); } } } The advice implementation is

responsible for continuing the interceptor chain by calling the proceed(). When the proceed() method is called, any additional advice is executed, before the method on the target object is executed.

62

Before Advice

• Before advice is ideal for actions that must occur before a method on a target object is called.

• It is called before the target method is invoked and can interrupt the invocation only by throwing an exception.

• implement the org.springframework.aop.MethodBeforeAdvice interface to create before advice

63

Check arguments are not null before execute

package com.virtusa.spring.inform; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class NullArgumentsNotAllowedBeforeAdvice implements MethodBeforeAdvice { public void before(Method method, Object[] arguments, Object target) throws Throwable { if (arguments == null || arguments.length == 0) { System.out.println("Number of arguments to check: " + arguments.length); return; } for (int i = 0; i < arguments.length; i++) { Object argument = arguments[i]; if (argument == null) { throw new IllegalArgumentException("Value for argument [" + i + "] is required but not present " + "for method [" + method + "]!"); } } } }

Sales-7.zip

64

<bean id="nullArgumentsNotAllowedBeforeAdvice" class="com.virtusa.spring.inform.NullArgumentsNotAllowedBeforeAdvice" /> <bean id="checkMessageBeforeSell" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name="mappedName" value="getSale" /> <property name="advice" ref="nullArgumentsNotAllowedBeforeAdvice" /> </bean> <bean id="seller" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <bean class="com.virtusa.spring.sale.RetailSeller"> <property name="sale" ref="newSale" /> </bean> </property> <property name="interceptorNames"> <list> <idref bean="checkMessageBeforeSell"/> <idref bean="sendTextMessageWhenSell"/> <idref bean="profilingAdvice"/> </list> </property> </bean>

65

After Advice

• After advice will be not executed if the target method throws an exception

• This advice type is ideal for actions that need access to the value returned by the target method and otherwise do not need to control the execution of the target method

• After advice cannot interrupt the execution of the method on the target object, since it’s called after that

• This advice type can interrupt the further invocation of the advisor chain by throwing an unchecked exception (java.lang.RuntimeException or java.lang.Error) or a checked exception that is declared in the signature of the method on the proxy object

66

Throws Advice

• Throws advice is called when the method execution on the target object throws a specific exception type

• This advice type is ideal for actions that need access to exceptions or otherwise need control when specific exception types are thrown

• Throws advice does not control the method execution because it’s called after exceptions are thrown

67

• ThrowsAdvice is probably the strangest interface that is part of the Spring Framework, since it doesn’t define any methods and yet must be implemented by advice classes.

• Instead of defining methods in the interface, Spring AOP recognizes and supports magic methods in classes that implement this interface

• The magic methods for throws advice supported by Spring AOP need to be named afterThrowing().

68

• These methods must have either of the two method signatures.

• Spring AOP will call the most specific afterThrowing() method defined in throws advice, which is the method with an exception argument type that’s type-compatible with the actual type that is thrown and closest to it in the class hierarchy.

69

Throwing Exceptions with Spring AOP Advice

• Each of the Spring AOP advice interfaces discussed allows you to throw exceptions. When an exception is thrown from an advice, one of three things happens:• Unchecked exceptions are passed to any other advice in the

advisor chain and eventually to the caller.

• Checked exceptions that are declared in the method signature of the target method are also passed to any other advice in the advisor chain and eventually to the caller.

• Checked exceptions that are not declared in the method signature of the target method will be wrapped in java.lang.reflect.UndeclaredThrowableException, which is unchecked.

70

• Many of the services offered by the Spring Framework use the Spring AOP framework internally.

• Each service typically has one or more ProxyFactoryBean classes to simplify the AOP configuration.

• These include the following:• Transaction management:

• Remote access

71

72

USA INDIA SRI LANKA UK

www.virtusa.com

© V I r t u s a C o r p o r a t i o n

"Virtusa" is a trademark of the company and a registered trademark in the EU and In India. "Productization" is a service mark of the company and a registered service mark in the United States.

"vRule" is a service mark of the company.

For more information please contact [email protected]