配置方式:通过工厂方法配置bean,通过FactoryBean配置bean
配置形式:基于注解的方式
静态工厂方法
1 /** 2 * 静态工厂方法:直接调用某一个类的静态方法就可以返回bean的实例 3 */ 4 public class StaticCarFactory { 5 private static Map<String, Car> cars = new HashMap<String, Car>(); 6 7 static{ 8 cars.put("audi", new Car("audi",123,123)); 9 cars.put("ford", new Car("ford",123,123)); 10 } 11 12 public static Car getCar(String name) { 13 return cars.get(name); 14 } 15 }
1 <!-- 通过静态工厂方法来配置bean,注意不是配置静态工厂方法实例,而是配置bean实例 --> 2 <bean id="car1" class="com.text.StaticCarFactory" factory-method="getCar"> 3 <constructor-arg value="audi"></constructor-arg> 4 </bean>
实例工厂方法
1 /** 2 * 实例工厂方法:实例工厂的方法,即先需要创建工厂本身,在调用 3 * 工厂的实例方法,再配置bean的实例 4 */ 5 public class InstanceCarFactory { 6 7 private Map<String, Car> cars = null; 8 9 public InstanceCarFactory() { 10 cars = new HashMap<String, Car>(); 11 cars.put("audi", new Car("audi",123,123)); 12 cars.put("ford", new Car("ford",123,123)); 13 } 14 15 public Car getCar(String name) { 16 return cars.get(name); 17 } 18 }
1 <!-- 配置工厂的实例 --> 2 <bean id="carFactory" class="com.text.InstanceCarFactory"></bean> 3 <!-- 通过实例工厂方法来配置bean --> 4 <bean id="car2" factory-bean="carFactory" factory-method="getCar"> 5 <constructor-arg value="ford"></constructor-arg> 6 </bean>
用FactoryBean配置bean
1 //自定义的FactoryBean需要实现提供的接口 2 public class CarFactoryBean implements FactoryBean<Car> { 3 4 private String name; 5 public void setName(String name) { 6 this.name = name; 7 } 8 9 @Override 10 public Car getObject() throws Exception { 11 // TODO Auto-generated method stub 12 return new Car(name,5000,500); 13 } 14 15 @Override 16 public Class<?> getObjectType() { 17 // TODO Auto-generated method stub 18 return Car.class; 19 } 20 21 @Override 22 public boolean isSingleton() { 23 // TODO Auto-generated method stub 24 return true; 25 } 26 27 28 }
1 <!-- 2 通过FactoryBean来配置bean的实例 3 class=指向FactoryBean的全类名 4 property=配置FactoryBean的属性 5 6 但实际返回的实例确是FactoryBean的getObject方法返回的实例 7 --> 8 <bean id="car" class="com.text.CarFactoryBean"> 9 <property name="name" value="bmw"></property> 10 </bean>
基于注解的方式配置bean,装配bean的属性
组建扫描:spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件
1. @Component 基本注解
2. @Respository 持久层
3. @Service 业务层
4. @Controller 表现层
可混用,ioc容器分辨不了,不过建议按层使用,value属性可标示beanName
可增加属性resource-pattern指定扫描的资源。如repository/*.class
可增加子节点
<context:exclude-filter type="annotation" expression=""/> 排除
<context:include-filter type="annotation" expression=""/> 包含(在use-default-filters【不使用默认注解】为false时使用)
expression中可填入如org.springframework.stereotype.Repository等包名
1 <!-- 指定ioc容器扫描的包 --> 2 <context:component-scan base-package="com.rep"></context:component-scan>
实例:autowire自动装配具有兼容类型的单个bean属性
@Controller public class UserController { @Autowire private UserService userService; public void controller() { System.out.println("controller"); userService.add(); } }
@Service public class UserService { public void add() { System.out.println("add"); } }
此时,就可以打印
controller
add
写到这里,突然产生了一个疑问,注解形式和xml形式是如何转化的
重新写了相同作用的xml
1 <bean id="userController" class="com.rep.UserController" > 2 <property name="userService" ref="userService"></property> 3 </bean> 4 5 <bean id="userService" class="com.rep.UserService"></bean>
在userController中的userService变量需要加上setter方法
运行得出相同结论。然后又产生一个问题,之前为啥用bean来着。。
如果不用bean呢?
1 private UserService userService = new UserService(); 2 3 public void controller() { 4 System.out.println("controller"); 5 userService.add(); 6 }
1 UserController userController = new UserController(); 2 //(UserController)ctx.getBean("userController"); 3 userController.controller();
写完对比后,就发现:用bean的原因是为了减少耦合,也就是Controller和Service之间不会产生关系,如果不用bean,Controller中需要new一个Service。而在用spring后,所有的bean都交给ioc容器管理,如果你有需要,跟ioc容器getBean即可。