sping slide 6

41
Collections for Bean Properties Java Collections Setting Collection for Bean Properties Defining List,Set,Map,Properties Setting Data Type for Collections Defining Concrete Collection Classes using Factory Bean Defining Concrete Collection Classes using Schema Defining Stand Alone Collections

Upload: patinijava

Post on 19-May-2015

675 views

Category:

Technology


5 download

TRANSCRIPT

Page 1: Sping Slide 6

Collections for Bean Properties

Java Collections

Setting Collection for Bean Properties

Defining List,Set,Map,Properties

Setting Data Type for Collections

Defining Concrete Collection Classes using Factory Bean

Defining Concrete Collection Classes using Schema

Defining Stand Alone Collections

Page 2: Sping Slide 6

The Java Collections framework defines a set of interfaces, implementations, and algorithms for different types of collections, such as lists, sets, and maps List, Set, and Map are the core interfaces representing three main types of collections. For each collection type, Java provides several implementations with different functions and characteristics from which you can choose. In Spring, these types of collections can be easily configured with a group of built-in XML tags, such as <list>, <set>, and <map>

Page 3: Sping Slide 6
Page 4: Sping Slide 6

Defining Collections for Bean Properties

Sometimes your bean properties may be of a collection type that contains multiple elements. You would like to configure these collectionproperties in Spring’s bean configuration file rather than by coding.

Based on our example before:-Suppose you are going to allow more than one suffix for your sequencegenerator. The suffixes will be appended to the sequence numbers withhyphens as the separators. You may consider accepting suffixes of arbitrarydata types and converting them into strings when appending to the sequence numbers.

Page 5: Sping Slide 6

First, let’s use a java.util.List collection to contain your suffixes. A list is an ordered and indexed collection whose elements can be accessed either by index or with a for-each loop.

public class SequenceGenerator {...private List<Object> suffixes;public void setSuffixes(List<Object> suffixes) {this.suffixes = suffixes;}public synchronized String getSequence() {StringBuffer buffer = new StringBuffer();...for (Object suffix : suffixes) {buffer.append("-");buffer.append(suffix);}return buffer.toString();}}

Using List example Bean

Page 6: Sping Slide 6

To define a property of java.util.List type in the bean configuration, you specify a <list> tag that contains the elements. The elements allowed inside the <list> tag can be a simple constant value specified by <value>, a bean reference by <ref>, an inner bean definitionby <bean>, or a null element by <null>. You can even embed other collections in acollection.

<bean id="sequenceGenerator"class="SequenceGenerator"><property name="prefixGenerator" ref="datePrefixGenerator" /><property name="initial" value="100000" /><property name="suffixes"><list><value>A</value><bean class="java.net.URL"><constructor-arg value="http" /><constructor-arg value="www.javafasttrack.com" /><constructor-arg value="/" /></bean><null /></list></property></bean>

Using List example Configuration

Page 7: Sping Slide 6

public class SequenceGenerator {...private Set<Object> suffixes;public void setSuffixes(Set<Object> suffixes) {this.suffixes = suffixes;}...}

To define a property of java.util.Set type, use the <set> tag to define the elements in thesame way as a list.<bean id="sequenceGenerator"class="SequenceGenerator">...<property name="suffixes"><set><value>A</value><bean class="java.net.URL"><constructor-arg value="http" /><constructor-arg value="www.javafasttrack.com" /><constructor-arg value="/" /></bean><null /></set></property></bean>

Using Set example Bean

Using Set example Configuration

Page 8: Sping Slide 6

Using Maps example Bean

public class SequenceGenerator {...private Map<Object, Object> suffixes;public void setSuffixes(Map<Object, Object> suffixes) {this.suffixes = suffixes;}public synchronized String getSequence() {StringBuffer buffer = new StringBuffer();...for (Map.Entry entry : suffixes.entrySet()) {buffer.append("-");buffer.append(entry.getKey());buffer.append("@");buffer.append(entry.getValue());}return buffer.toString();}}

Page 9: Sping Slide 6

<bean id="sequenceGenerator“ Using Maps example configuration class="SequenceGenerator"><property name="suffixes"><map><entry><key><value>type</value></key><value>A</value></entry><entry><key><value>url</value></key><bean class="java.net.URL"><constructor-arg value="http" /><constructor-arg value="www.apress.com" /><constructor-arg value="/" /></bean></entry></map></property></bean>

Page 10: Sping Slide 6

There are shortcuts to defining map keys and values as attributes of the <entry> tag. If they are simple constant values, you can define them by key and value. If they are bean references,you can define them by key-ref and value-ref.

<bean id="sequenceGenerator"class="com.apress.springrecipes.sequence.SequenceGenerator">...<property name="suffixes"><map><entry key="type" value="A" /><entry key="url"><bean class="java.net.URL"><constructor-arg value="http" /><constructor-arg value="www.apress.com" /><constructor-arg value="/" /></bean></entry></map></property></bean>

Page 11: Sping Slide 6

Using java.util.Properties

A java.util.Properties collection is very similar to a map. It also implements the java.util.Map interface and stores entries in key/value pairs. The only difference is that the keys and values of a Properties collection are always strings....

Page 12: Sping Slide 6

public class SequenceGenerator {...private Properties suffixes; java.util.Properties Bean example

public void setSuffixes(Properties suffixes) {this.suffixes = suffixes;}...}To define a java.util.Properties collection in Spring, use the <props> tag with multiple<prop> tags as children. Each <prop> tag must have a key attribute defined and the correspondingvalue enclosed.<bean id="sequenceGenerator“ class="SequenceGenerator">...<property name="suffixes"><props><prop key="type">A</prop><prop key="url">http://www.jftcom/</prop></props></property> </bean>

Page 13: Sping Slide 6

Merging the Collection of the Parent BeanIf you define your beans with inheritance, a child bean’s collection can be merged with that ofits parent by setting the merge attribute to true. For a <list> collection, the child elements willbe appended after the parent’s to preserve the order. So, the following sequence generatorwill have four suffixes: A, B, A, and C.

Page 14: Sping Slide 6

Merging the Collection of the Parent Bean Example

<beans ...> <bean id="baseSequenceGenerator"class="SequenceGenerator"><property name="prefixGenerator" ref="datePrefixGenerator" /><property name="initial" value="100000" /><property name="suffixes"><list><value>A</value><value>B</value></list></property></bean><bean id="sequenceGenerator" parent="baseSequenceGenerator"><property name="suffixes"><list merge="true"><value>A</value><value>C</value></list></property>

Page 15: Sping Slide 6

Merging the Collection of the Parent Bean Example (Contd ..)</bean>...</beans>For a <set> or <map> collection, the child elements will overwrite the parent’s if they havethe same value. So, the following sequence generator will have three suffixes: A, B, and C.<beans ...><bean id="baseSequenceGenerator"class="com.apress.springrecipes.sequence.SequenceGenerator"><property name="prefixGenerator" ref="datePrefixGenerator" /><property name="initial" value="100000" /><property name="suffixes"><set><value>A</value><value>B</value></set></property></bean>

Page 16: Sping Slide 6

<bean id="sequenceGenerator" parent="baseSequenceGenerator"><property name="suffixes"><set merge="true"><value>A</value><value>C</value></set></property></bean>...</beans>

Page 17: Sping Slide 6

Specifying the Data Type for Collection Elements

By default, Spring treats every element in a collection as a string. You have to specify the data type for your collection elements if you are not going to use them as strings. You can either specify the data type for each collectionelement by the type attribute of the<value> tag, or specify the data type forall elements by the value-type attribute of the collection tag.

Page 18: Sping Slide 6

Now suppose you are going to accept a list of integer numbers as the suffixes of your sequence generator. Each number will be formatted into four digits by an instance of java.text. DecimalFormat.

public class SequenceGenerator {...private List<Object> suffixes;public void setSuffixes(List<Object> suffixes) {this.suffixes = suffixes;}public synchronized String getSequence() {StringBuffer buffer = new StringBuffer();...DecimalFormat formatter = new DecimalFormat("0000");for (Object suffix : suffixes) {buffer.append("-");buffer.append(formatter.format((Integer) suffix));}return buffer.toString();}}

Page 19: Sping Slide 6

<bean id="sequenceGenerator"class="com.apress.springrecipes.sequence.SequenceGenerator"><property name="prefixGenerator" ref="datePrefixGenerator" /><property name="initial" value="100000" /><property name="suffixes"><list><value>5</value>However, when you run this application, you will encounter a ClassCastException, indicating that the suffixes cannot be cast into integers because their type is String. Spring treats every element in a collection as a string by default<value>10</value><value>20</value></list></property></bean>

Page 20: Sping Slide 6

<bean id="sequenceGenerator"class="SequenceGenerator">...<property name="suffixes"><list><value type="int">5</value><value type="int">10</value><value type="int">20</value></list></property></bean>

Or you may set the value-type attribute of the collection tag to specify the type for all elements in this collection.<bean id="sequenceGenerator"class="SequenceGenerator">...<property name="suffixes"><list value-type="int"><value>5</value><value>10</value><value>20</value></list></property></bean>

Page 21: Sping Slide 6

In Java 1.5 or higher, you can define your suffixes list with a type-safe collection that stores integers....public class SequenceGenerator {...private List<Integer> suffixes;public void setSuffixes(List<Integer> suffixes) {this.suffixes = suffixes;}public synchronized String getSequence() {StringBuffer buffer = new StringBuffer();...DecimalFormat formatter = new DecimalFormat("0000");for (int suffix : suffixes) {buffer.append("-");buffer.append(formatter.format(suffix));}

Page 22: Sping Slide 6

return buffer.toString();}}Once you have defined your collections in a type-safe way, Spring will be able to read thecollection’s type information through reflection. In this way, you no longer need to specify thevalue-type attribute of <list>.<bean id="sequenceGenerator“ class="SequenceGenerator">...<property name="suffixes"><list><value>5</value><value>10</value><value>20</value></list></property></bean>

Page 23: Sping Slide 6

class CarFactory{

Car static newInstance(){

return new Maruthi();}

}

interface Car{

}

Maruthi implements Car{

}

Page 24: Sping Slide 6

Defining Collections Using Factory Beans and theUtility Schema

When using the basic collection tags to define collections, you can’t specify the concrete class of a collection, such as LinkedList, TreeSet, orTreeMap.Moreover, you cannot share a collection among different beans by defining it as a stand-alone bean for other beans to refer to/

Spring provides a couple of options to overcome the shortcomings of thebasic collection tags. One option is to use corresponding collection factorybeans like ListFactoryBean,SetFactoryBean, and MapFactoryBean. A factorybean is a special kind of Spring bean that is used for creating another bean.The second option is to use collection tags such as <util:list>, <util:set>, and<util:map> in the util schema introduced in Spring 2.x..

Page 25: Sping Slide 6

<bean id="sequenceGenerator"class="SequenceGenerator"><property name="prefixGenerator" ref="datePrefixGenerator" /><property name="initial" value="100000" />

<property name="suffixes"><bean class="org.springframework.beans.factory.config.SetFactoryBean"><property name="targetSetClass"><value>java.util.TreeSet</value></property><property name="sourceSet"><set><value>5</value><value>10</value><value>20</value></set></property></bean></property></bean>

Page 26: Sping Slide 6

Or you can use a collection tag in the util schema to define a collection and set its target class (e.g., by the set-class attribute of <util:set>). But you must remember to add the util schema definition to your <beans> root element.<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-2.5.xsd"><bean id="sequenceGenerator“ class=“SequenceGenerator">...<property name="suffixes"><util:set set-class="java.util.TreeSet"><value>5</value><value>10</value><value>20</value></util:set></property></bean>...</beans>

Page 27: Sping Slide 6

Defining Stand-Alone Collections

Another advantage of collection factory beans is that you can define a collection as

a standalone bean for other beans to refer to. For example, you can define a

stand-alone set by using SetFactoryBean.

Page 28: Sping Slide 6

<beans ...><bean id="sequenceGenerator"class="SequenceGenerator">...<property name="suffixes"><ref local="suffixes" /></property></bean><bean id="suffixes"class="org.springframework.beans.factory.config.SetFactoryBean"><property name="sourceSet"><set><value>5</value><value>10</value><value>20</value></set></property></bean>...</beans>

Page 29: Sping Slide 6

Or you can define a stand-alone set by using the <util:set> tag in the util schema.<beans ...><bean id="sequenceGenerator“ class="SequenceGenerator">...<property name="suffixes"><ref local="suffixes" /></property></bean>

<util:set id="suffixes"><value>5</value><value>10</value><value>20</value></util:set>...</beans>

Page 30: Sping Slide 6

Scanning Components from the Classpath

In order for the Spring IoC container to manage your components, you declare them one

By one in the bean configuration file. However, it can save you a lot of work if Spring can

Automatically detect your components without manual configuration.

Spring 2.5 provides a powerful feature called component scanning. It can automatically

scan, detect, and instantiate your components with particular stereotype annotations from

The classpath. The basic annotation denoting a Spring-managed component is

@Component. Other more particular stereotypes include @Repository, @Service, and

@Controller. They denote components in the persistence, service, and presentation

layers, respectively.

Page 31: Sping Slide 6

Scanning Components AutomaticallyThe component scanning feature provided by Spring 2.5 can automatically scan, detect,and instantiate your components from the classpath. By default, Spring is able to detectAll components with a stereotype annotation. The basic annotation type that denotes aSpringmanaged component is @Component. You can apply it to your SequenceDaoImplclass.

import org.springframework.stereotype.Component;@Componentpublic class SequenceDaoImpl implements SequenceDao {...}Also, you apply this stereotype annotation to the SequenceService class for Spring todetect it. In addition, you apply the @Autowired annotation to the DAO field for Spring toAutowire it by type.

@Componentpublic class SequenceService {@Autowiredprivate SequenceDao sequenceDao;...}

Page 32: Sping Slide 6

With the stereotype annotations applied to your component classes, you can

ask Spring to scan them by declaring a single XML element,

<context:component-scan>. In this element, you need to specify the package

for scanning your components. Then the specified package and all its

subpackages will be scanned. You can use commas to separate multiple

packages for scanning.

Page 33: Sping Slide 6

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd"><context:component-scan base-

package="com.jft.springcore.sequence" /></beans>

Page 34: Sping Slide 6

The @Component annotation is the basic stereotype fordenoting components of general purposes. Actually, thereare other specific stereotypes denoting components inDifferent layers. First, the @Repository stereotype denotesa DAO component in the persistence layer.

import org.springframework.stereotype.Repository;@Repositorypublic class SequenceDaoImpl implements SequenceDao {...}

Page 35: Sping Slide 6

Then, the @Service stereotype denotes a servicecomponent in the service layer.

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;

@Servicepublic class SequenceService {@Autowiredprivate SequenceDao sequenceDao;...}

Page 36: Sping Slide 6

Filtering Components to ScanBy default, Spring will detect all classes annotated with @Component,@Repository, @Service,@Controller, or your custom annotation type that isitself annotated with @Component. You can customize the scan by applying one or more include/exclude filters.

<beans ...><context:component-scan base-package="com.apress.springrecipes.sequence"><context:include-filter type="regex"expression="com\.apress\.springrecipes\.sequence\..*Dao.*" /><context:include-filter type="regex"expression="com\.apress\.springrecipes\.sequence\..*Service.*" /><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller" /></context:component-scan></beans>

Page 37: Sping Slide 6

Creating Beans by Invoking a Static Factory Method

Spring supports creating a bean by invoking a static factory method, which

should be specified in the factory-method attribute.

Static factory method will encapsulate the object-creation process

.

Page 38: Sping Slide 6

class CarFactory{

Car static newInstance(){

return new Maruthi();}

}

interface Car{

}

Maruthi implements Car{

}

Page 39: Sping Slide 6

public class ProductCreator {public static Product createProduct(String productId) {if ("aaa".equals(productId)) {return new Battery("AAA", 2.5);} else if ("cdrw".equals(productId)) {return new Disc("CD-RW", 1.5);}throw new IllegalArgumentException("Unknown product");}}

For example, you can write the following createProduct() static factory method to create a product from a predefined product ID. According to theproduct ID, this method will decide which concrete product class to instantiate.If there is no product matching this ID, it will throw an IllegalArgumentException

Page 40: Sping Slide 6

To declare a bean created by a static factory method, you specify the class hosting the factory method in the class attribute and the factory method’sname in the factory-method attribute. Finally, you pass the method argumentsby using the <constructor-arg> elements.

<beans ...><bean id="aaa" class="ProductCreator"factory-method="createProduct"><constructor-arg value="aaa" /></bean>

<bean id="cdrw" class="ProductCreator“factory-method="createProduct"><constructor-arg value="cdrw" /></bean></beans>

Page 41: Sping Slide 6

In case of any exception thrown by the factory method, Spring will wrap it with a

BeanCreationException. The equivalent code snippet for the preceding bean

Configuration is shown following:

Product aaa = ProductCreator.createProduct("aaa");

Product cdrw = ProductCreator.createProduct("cdrw");