本周事情比较多(明天去学校参加活动),因此学的知识比较少
通过工厂方法配置Bean
Bean的配置方式,除了全类名(反射机制)之外,还可以通过**工厂方法(静态工厂方法&实例工厂方法)**以及FactoryBean的方式来配置
1. 通过调用静态工厂方法创建Bean
- 静态工厂方法:将对象创建的过程封装到静态方法中.`当客户端需要对象时,只需要简单的调用静态方法,而不用关心创建对象的细节
- 要声明通过静态方法创建的Bean,需要在Bean的class属性里指定拥有该工厂的类,同时在factory-method属性里指定该工厂方法的名称.最后,使用
<constructor-arg>
元素为该方法传递方法参数
代码示例:
Car.java
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 33 34 35 36 37 38 39 40 41 42 43 44 45
| package factory;
class Car { private String brand; private int speed; private double price;
Car(String brand, int speed, double price) { this.brand = brand; this.speed = speed; this.price = price; }
@Override public String toString() { return "Car{" + "brand='" + brand + '\'' + ", speed=" + speed + ", price=" + price + '}'; }
public void setBrand(String brand) { this.brand = brand; }
public void setSpeed(int speed) { this.speed = speed; }
public void setPrice(double price) { this.price = price; } }
|
2. 通过调用实例工厂方法创建Bean
- 实例工厂方法:
将对象的创建过程封装到另外一个对象实例的方法里.
当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节
- 要声明通过实例工厂方法创建的Bean
- 在Bean的factory-bean属性里指定拥有该工厂方法的Bean
- 在factory-method属性里指定该工厂方法的名称
- 使用
<constructor-args>
元素为工厂方法传递方法参数
代码示例:
instanceFactory.java
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
| package factory;
import java.util.HashMap; import java.util.Map;
public class InstanceFactory { private Map<String, Car> cars = new HashMap<>();
public InstanceFactory() { cars.put("Audi", new Car("Audi", 100, 400000)); cars.put("Ford", new Car("Ford", 50, 200000)); }
public Car getCar(String name) { return cars.get(name); } }
|
Car.java
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 33 34 35 36 37 38 39 40 41 42 43 44 45
| package factory;
class Car { private String brand; private int speed; private double price;
Car(String brand, int speed, double price) { this.brand = brand; this.speed = speed; this.price = price; }
@Override public String toString() { return "Car{" + "brand='" + brand + '\'' + ", speed=" + speed + ", price=" + price + '}'; }
public void setBrand(String brand) { this.brand = brand; }
public void setSpeed(int speed) { this.speed = speed; }
public void setPrice(double price) { this.price = price; } }
|
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package factory;
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory/factory.xml"); Car car1 = (Car) applicationContext.getBean("car1"); System.out.println(car1); } }
|
factory.xml
1 2 3 4 5 6 7 8 9 10 11 12
| <?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.xsd">
<bean id="instanceFactory" class="factory.InstanceFactory"/>
<bean id="car1" factory-bean="instanceFactory" factory-method="getCar"> <constructor-arg value="Ford"/> </bean> </beans>
|
运行结果:
1
| Car{brand='Ford', speed=50, price=200000.0}
|
通过FactoryBean配置Bean
配置Bean的第三种方式:FactoryBean
FactoryBean需要实现FactoryBean接口,接口中有三个方法:
- getObject()
- getObjectType()
- isSingleton()
FactoryBean.java
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 33 34 35 36 37 38
| package factoryBean;
public class FactoryBean implements org.springframework.beans.factory.FactoryBean<Car> {
private String brand;
public void setBrand(String brand) { this.brand = brand; }
@Override public Car getObject() throws Exception { return new Car(brand, 100, 400000); }
@Override public Class<?> getObjectType() { return Car.class; }
@Override public boolean isSingleton() { return true; } }
|
Car.java
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 33 34 35 36 37 38 39 40 41 42 43 44 45
| package factoryBean;
class Car { private String brand; private int speed; private double price;
Car(String brand, int speed, double price) { this.brand = brand; this.speed = speed; this.price = price; }
@Override public String toString() { return "Car{" + "brand='" + brand + '\'' + ", speed=" + speed + ", price=" + price + '}'; }
public void setBrand(String brand) { this.brand = brand; }
public void setSpeed(int speed) { this.speed = speed; }
public void setPrice(double price) { this.price = price; } }
|
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package factoryBean;
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factoryBean/BeanFactory.xml"); Car car = (Car) applicationContext.getBean("car"); System.out.println(car); } }
|
BeanFactory.xml
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?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.xsd">
<bean id="car" class="factoryBean.FactoryBean"> <property name="brand" value="Audi"/> </bean> </beans>
|
运行结果为:
1
| Car{brand='Audi', speed=100, price=400000.0}
|
通过注解配置Bean
配置Bean除了基于XML文件的形式,还可以基于注解的方式(基于注解配置Bean&基于注解装配Bean的属性)
在ClassPath中扫描组件
组件扫描(component scanning):Spring能够从classpath下自动扫描侦测和实例化具有特定注解的组件
特定组件包括:
- @Component:基本注解,标识了一个受Spring管理的组件
- @Respository:标识永久层组件
- @Service:标识服务层(业务层)组件
- @Controller:标识表现层组件
对于扫描到的组件,Spring有默认的命名策略:通过非限定类名,第一个字母小写.也可以在注解中通过value属性值标识组件的名称
当在组件上使用了特定的注解之后,还需要在Spring的配置文件中声明<context:component-scan>
:
base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类
当需要扫描多个包时,可以使用逗号分隔
如果仅希望扫描特定的类而非基类包下的所有类,可使用resource-patten属性过滤特定的类,示例:
1 2 3
| <context:component-scan base-package="com.swzdl.spring.beans" resource-patten="autowire/*.class"/>
|
<context:include-filter>
子节点表示要包含的目标类
<context:exclude-filter>
子节点表示要排除在外的目标类
<context:component-scan>
下可以拥有若干个<context:include-filter>
和<context:exclude-filter>
子节点