Sping Slide 6
Upcoming SlideShare
Loading in...5
×
 

Sping Slide 6

on

  • 946 views

 

Statistics

Views

Total Views
946
Views on SlideShare
946
Embed Views
0

Actions

Likes
1
Downloads
10
Comments
0

0 Embeds 0

No embeds

Accessibility

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Sping Slide 6 Sping Slide 6 Presentation Transcript

  • 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
  • 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>
  •  
  • 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 collection
    • properties 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 sequence
    • generator. The suffixes will be appended to the sequence numbers with
    • hyphens as the separators. You may consider accepting suffixes of arbitrary
    • data types and converting them into strings when appending to the
    • sequence numbers.
  • 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(&quot;-&quot;); buffer.append(suffix); } return buffer.toString(); } } Using List example Bean
  • 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 definition by <bean>, or a null element by <null>. You can even embed other collections in a collection. <bean id=&quot;sequenceGenerator&quot; class=&quot;SequenceGenerator&quot;> <property name=&quot;prefixGenerator&quot; ref=&quot;datePrefixGenerator&quot; /> <property name=&quot;initial&quot; value=&quot;100000&quot; /> <property name=&quot;suffixes&quot;> <list> <value>A</value> <bean class=&quot;java.net.URL&quot;> <constructor-arg value=&quot;http&quot; /> <constructor-arg value=&quot;www.javafasttrack.com&quot; /> <constructor-arg value=&quot;/&quot; /> </bean> <null /> </list> </property> </bean> Using List example Configuration
  • 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 the same way as a list. <bean id=&quot;sequenceGenerator&quot; class=&quot;SequenceGenerator&quot;> ... <property name=&quot;suffixes&quot;> <set> <value>A</value> <bean class=&quot;java.net.URL&quot;> <constructor-arg value=&quot;http&quot; /> <constructor-arg value=&quot;www.javafasttrack.com&quot; /> <constructor-arg value=&quot;/&quot; /> </bean> <null /> </set> </property> </bean> Using Set example Bean Using Set example Configuration
  • 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(&quot;-&quot;); buffer.append(entry.getKey()); buffer.append(&quot;@&quot;); buffer.append(entry.getValue()); } return buffer.toString(); } }
  • <bean id=&quot;sequenceGenerator“ Using Maps example configuration class=&quot;SequenceGenerator&quot;> <property name=&quot;suffixes&quot;> <map> <entry> <key> <value>type</value> </key> <value>A</value> </entry> <entry> <key> <value>url</value> </key> <bean class=&quot;java.net.URL&quot;> <constructor-arg value=&quot;http&quot; /> <constructor-arg value=&quot;www.apress.com&quot; /> <constructor-arg value=&quot;/&quot; /> </bean> </entry> </map> </property> </bean>
  • 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=&quot;sequenceGenerator&quot; class=&quot;com.apress.springrecipes.sequence.SequenceGenerator&quot;> ... <property name=&quot;suffixes&quot;> <map> <entry key=&quot;type&quot; value=&quot;A&quot; /> <entry key=&quot;url&quot;> <bean class=&quot;java.net.URL&quot;> <constructor-arg value=&quot;http&quot; /> <constructor-arg value=&quot;www.apress.com&quot; /> <constructor-arg value=&quot;/&quot; /> </bean> </entry> </map> </property> </bean>
  • 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....
  • 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 corresponding value enclosed. <bean id=&quot;sequenceGenerator“ class=&quot;SequenceGenerator&quot;> ... <property name=&quot;suffixes&quot;> <props> <prop key=&quot;type&quot;>A</prop> <prop key=&quot;url&quot;>http://www.jftcom/</prop> </props></property> </bean>
  • Merging the Collection of the Parent Bean If you define your beans with inheritance, a child bean’s collection can be merged with that of its parent by setting the merge attribute to true. For a <list> collection, the child elements will be appended after the parent’s to preserve the order. So, the following sequence generator will have four suffixes: A, B, A, and C.
  • Merging the Collection of the Parent Bean Example <beans ...> <bean id=&quot;baseSequenceGenerator&quot; class=&quot;SequenceGenerator&quot;> <property name=&quot;prefixGenerator&quot; ref=&quot;datePrefixGenerator&quot; /> <property name=&quot;initial&quot; value=&quot;100000&quot; /> <property name=&quot;suffixes&quot;> <list> <value>A</value> <value>B</value> </list> </property> </bean> <bean id=&quot;sequenceGenerator&quot; parent=&quot;baseSequenceGenerator&quot;> <property name=&quot;suffixes&quot;> <list merge=&quot;true&quot; > <value>A</value> <value>C</value> </list> </property>
  • 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 have the same value. So, the following sequence generator will have three suffixes: A, B, and C. <beans ...> <bean id=&quot;baseSequenceGenerator&quot; class=&quot;com.apress.springrecipes.sequence.SequenceGenerator&quot;> <property name=&quot;prefixGenerator&quot; ref=&quot;datePrefixGenerator&quot; /> <property name=&quot;initial&quot; value=&quot;100000&quot; /> <property name=&quot;suffixes&quot;> <set> <value>A</value> <value>B</value> </set> </property> </bean>
  • <bean id=&quot;sequenceGenerator&quot; parent=&quot;baseSequenceGenerator&quot;> <property name=&quot;suffixes&quot;> <set merge=&quot;true&quot;> <value>A</value> <value>C</value> </set> </property> </bean> ... </beans>
  • 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 collection
    • element by the type attribute of the<value> tag, or specify the data type for
    • all elements by the value-type attribute of the collection tag.
  • 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(&quot;0000&quot;); for (Object suffix : suffixes) { buffer.append(&quot;-&quot;); buffer.append(formatter.format((Integer) suffix)); } return buffer.toString(); } }
  • <bean id=&quot;sequenceGenerator&quot; class=&quot;com.apress.springrecipes.sequence.SequenceGenerator&quot;> <property name=&quot;prefixGenerator&quot; ref=&quot;datePrefixGenerator&quot; /> <property name=&quot;initial&quot; value=&quot;100000&quot; /> <property name=&quot;suffixes&quot;> <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>
  • <bean id=&quot;sequenceGenerator&quot; class=&quot;SequenceGenerator&quot;> ... <property name=&quot;suffixes&quot;> <list> <value type=&quot;int&quot;>5</value> <value type=&quot;int&quot;>10</value> <value type=&quot;int&quot;>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=&quot;sequenceGenerator&quot; class=&quot;SequenceGenerator&quot;> ... <property name=&quot;suffixes&quot;> <list value-type=&quot;int&quot;> <value>5</value> <value>10</value> <value>20</value> </list> </property> </bean>
  • 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(&quot;0000&quot;); for (int suffix : suffixes) { buffer.append(&quot;-&quot;); buffer.append(formatter.format(suffix)); }
  • return buffer.toString(); } } Once you have defined your collections in a type-safe way, Spring will be able to read the collection’s type information through reflection. In this way, you no longer need to specify the value-type attribute of <list>. <bean id=&quot;sequenceGenerator“ class=&quot;SequenceGenerator&quot;> ... <property name=&quot;suffixes&quot;> <list> <value>5</value> <value>10</value> <value>20</value> </list> </property> </bean>
  • class CarFactory{ Car static newInstance(){ return new Maruthi(); } } interface Car{ } Maruthi implements Car{ }
  • Defining Collections Using Factory Beans and the Utility Schema
    • When using the basic collection tags to define collections, you can’t
    • specify the concrete class of a collection, such as LinkedList, TreeSet, or
    • TreeMap.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 the
    • basic collection tags. One option is to use corresponding collection factory
    • beans like ListFactoryBean,SetFactoryBean, and MapFactoryBean. A factory
    • bean 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..
  • <bean id=&quot;sequenceGenerator&quot; class=&quot;SequenceGenerator&quot;> <property name=&quot;prefixGenerator&quot; ref=&quot;datePrefixGenerator&quot; /> <property name=&quot;initial&quot; value=&quot;100000&quot; /> <property name=&quot;suffixes&quot;> <bean class=&quot;org.springframework.beans.factory.config.SetFactoryBean&quot;> <property name=&quot; targetSetClass &quot;> <value> java.util.TreeSet </value> </property> <property name=&quot;sourceSet&quot;> <set> <value>5</value> <value>10</value> <value>20</value> </set> </property> </bean> </property> </bean>
  • 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=&quot;http://www.springframework.org/schema/beans&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:util=&quot;http://www.springframework.org/schema/util&quot; xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd&quot;> <bean id=&quot;sequenceGenerator“ class=“SequenceGenerator&quot;> ... <property name=&quot;suffixes&quot;> <util:set set-class=&quot;java.util.TreeSet&quot;> <value>5</value> <value>10</value> <value>20</value> </util:set> </property> </bean> ... </beans>
  • 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.
  • <beans ...> <bean id=&quot;sequenceGenerator&quot; class=&quot;SequenceGenerator&quot;> ... <property name=&quot;suffixes&quot;> <ref local=&quot;suffixes&quot; /> </property> </bean> <bean id=&quot;suffixes&quot; class=&quot;org.springframework.beans.factory.config.SetFactoryBean&quot;> <property name=&quot;sourceSet&quot;> <set> <value>5</value> <value>10</value> <value>20</value> </set> </property> </bean> ... </beans>
  • Or you can define a stand-alone set by using the <util:set> tag in the util schema. <beans ...> <bean id=&quot;sequenceGenerator“ class=&quot;SequenceGenerator&quot;> ... <property name=&quot;suffixes&quot;> <ref local=&quot;suffixes&quot; /> </property> </bean> <util:set id=&quot;suffixes&quot;> <value>5</value> <value>10</value> <value>20</value> </util:set> ... </beans>
  • 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.
    • Scanning Components Automatically
    • The 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 detect
    • All components with a stereotype annotation. The basic annotation type that denotes a
    • Springmanaged component is @Component. You can apply it to your SequenceDaoImpl
    • class.
    • import org.springframework.stereotype.Component;
    • @Component
    • public class SequenceDaoImpl implements SequenceDao {
    • ...
    • }
    • Also, you apply this stereotype annotation to the SequenceService class for Spring to
    • detect it. In addition, you apply the @Autowired annotation to the DAO field for Spring to
    • Autowire it by type.
    • @Component
    • public class SequenceService {
    • @Autowired
    • private SequenceDao sequenceDao;
    • ...
    • }
    • 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.
    • <beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
    • xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    • xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
    • xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans
    • http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    • http://www.springframework.org/schema/context
    • http://www.springframework.org/schema/context/spring-context-
    • 2.5.xsd&quot;>
    • <context:component-scan base-package=&quot;com.jft.springcore.sequence&quot; />
    • </beans>
    • The @Component annotation is the basic stereotype for
    • denoting components of general purposes. Actually, there
    • are other specific stereotypes denoting components in
    • Different layers. First, the @Repository stereotype denotes
    • a DAO component in the persistence layer.
    • import org.springframework.stereotype.Repository;
    • @Repository
    • public class SequenceDaoImpl implements SequenceDao {
    • ...
    • }
    • Then, the @Service stereotype denotes a service
    • component in the service layer.
    • import org.springframework.beans.factory.annotation.Autowired;
    • import org.springframework.stereotype.Service;
    • @Service
    • public class SequenceService {
    • @Autowired
    • private SequenceDao sequenceDao;
    • ...
    • }
    • Filtering Components to Scan
    • By default, Spring will detect all classes annotated with @Component,
    • @Repository, @Service,@Controller, or your custom annotation type that is
    • itself annotated with @Component.
    • You can customize the scan by applying one or more include/exclude filters.
    • <beans ...>
    • <context:component-scan base-package=&quot;com.apress.springrecipes.sequence&quot;>
    • <context:include-filter type=&quot; regex &quot;
    • expression=&quot;com.apress.springrecipes.sequence..*Dao.*&quot; />
    • <context:include-filter type=&quot; regex &quot;
    • expression=&quot;com.apress.springrecipes.sequence..*Service.*&quot; />
    • <context:exclude-filter type=&quot; annotation &quot;
    • expression=&quot;org.springframework.stereotype.Controller&quot; />
    • </context:component-scan>
    • </beans>
    • 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
    • .
  • class CarFactory{ Car static newInstance(){ return new Maruthi(); } } interface Car{ } Maruthi implements Car{ }
    • public class ProductCreator {
    • public static Product createProduct(String productId) {
    • if (&quot;aaa&quot;.equals(productId)) {
    • return new Battery(&quot;AAA&quot;, 2.5);
    • } else if (&quot;cdrw&quot;.equals(productId)) {
    • return new Disc(&quot;CD-RW&quot;, 1.5);
    • }
    • throw new IllegalArgumentException(&quot;Unknown product&quot;);
    • }
    • }
    For example, you can write the following createProduct() static factory method to create a product from a predefined product ID. According to the product ID, this method will decide which concrete product class to instantiate. If there is no product matching this ID, it will throw an IllegalArgumentException
    • 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’s
    • name in the factory-method attribute. Finally, you pass the method arguments
    • by using the <constructor-arg> elements.
    • <beans ...>
    • <bean id=&quot;aaa&quot; class=&quot;ProductCreator&quot;
    • factory-method=&quot;createProduct&quot;>
    • <constructor-arg value=&quot;aaa&quot; />
    • </bean>
    • <bean id=&quot;cdrw&quot; class=&quot;ProductCreator“
    • factory-method=&quot;createProduct&quot;>
    • <constructor-arg value=&quot;cdrw&quot; />
    • </bean>
    • </beans>
    • 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(&quot;aaa&quot;);
    • Product cdrw = ProductCreator.createProduct(&quot;cdrw&quot;);