Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (5.49 MB, 753 trang )
9799ch04.qxd
94
4/10/08
10:53 AM
Page 94
CHAPTER 4 ■ ADVANCED SPRING IOC CONTAINER
package com.apress.springrecipes.shop;
public abstract class Product {
private String name;
private double price;
public Product() {}
public Product(String name, double price) {
this.name = name;
this.price = price;
}
// Getters and Setters
...
public String toString() {
return name + " " + price;
}
}
Then you create two product subclasses, Battery and Disc. Each of them has its own
properties.
package com.apress.springrecipes.shop;
public class Battery extends Product {
private boolean rechargeable;
public Battery() {
super();
}
public Battery(String name, double price) {
super(name, price);
}
// Getters and Setters
...
}
package com.apress.springrecipes.shop;
public class Disc extends Product {
9799ch04.qxd
4/10/08
10:53 AM
Page 95
CHAPTER 4 ■ ADVANCED SPRING IOC CONTAINER
private int capacity;
public Disc() {
super();
}
public Disc(String name, double price) {
super(name, price);
}
// Getters and Setters
...
}
To define some products in the Spring IoC container, you create the following bean configuration file:
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.5.xsd">
If there’s no
the setter method. The preceding bean configuration is equivalent to the following code
snippet:
Product aaa = new Battery();
aaa.setName("AAA");
aaa.setPrice(2.5);
aaa.setRechargeable(true);
Product cdrw = new Disc();
cdrw.setName("CD-RW");
cdrw.setPrice(1.5);
cdrw.setCapacity(700);
95
9799ch04.qxd
96
4/10/08
10:53 AM
Page 96
CHAPTER 4 ■ ADVANCED SPRING IOC CONTAINER
Otherwise, if there are one or more
invoke the most appropriate constructor that matches your arguments.
As there is no constructor ambiguity for the Product class and subclasses, the preceding
bean configuration is equivalent to the following code snippet:
Product aaa = new Battery("AAA", 2.5);
aaa.setRechargeable(true);
Product cdrw = new Disc("CD-RW", 1.5);
cdrw.setCapacity(700);
You can write the following Main class to test your products by retrieving them from the
Spring IoC container:
package com.apress.springrecipes.shop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) throws Exception {
ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml");
Product aaa = (Product) context.getBean("aaa");
Product cdrw = (Product) context.getBean("cdrw");
System.out.println(aaa);
System.out.println(cdrw);
}
}
9799ch04.qxd
4/10/08
10:53 AM
Page 97
CHAPTER 4 ■ ADVANCED SPRING IOC CONTAINER
4-2. Creating Beans by Invoking a Static Factory Method
Problem
You would like to create a bean in the Spring IoC container by invoking a static factory method,
whose purpose is to encapsulate the object-creation process in a static method. The client
who requests an object can simply make a call to this method without knowing about the
creation detail.
Solution
Spring supports creating a bean by invoking a static factory method, which should be specified in the factory-method attribute.
How It Works
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.
package com.apress.springrecipes.shop;
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");
}
}
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
factory-method="createProduct">
factory-method="createProduct">
97
9799ch04.qxd
98
4/10/08
10:53 AM
Page 98
CHAPTER 4 ■ ADVANCED SPRING IOC CONTAINER
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");
4-3. Creating Beans by Invoking an Instance Factory Method
Problem
You would like to create a bean in the Spring IoC container by invoking an instance factory
method, whose purpose is to encapsulate the object-creation process in a method of another
object instance. The client who requests an object can simply make a call to this method without knowing about the creation detail.
Solution
Spring supports creating a bean by invoking an instance factory method. The bean instance
should be specified in the factory-bean attribute, while the factory method should be specified in the factory-method attribute.
How It Works
For example, you can write the following ProductCreator class by using a configurable map to
store the predefined products. The createProduct() instance factory method finds a product
by looking up the supplied productId in the map. If there is no product matching this ID, it will
throw an IllegalArgumentException.
package com.apress.springrecipes.shop;
...
public class ProductCreator {
private Map
public void setProducts(Map
this.products = products;
}
public Product createProduct(String productId) {
Product product = products.get(productId);
if (product != null) {
return product;
}
throw new IllegalArgumentException("Unknown product");
}
}