PART ONE 工厂配置
通过工厂方法,FactoryBean 的方法配置Bean
一:静态工厂方法
静态工厂方法完成Bean 配置:通过直接调用某个类的静态方法就可以放回Bean实例
测试代码:
1. Bean 对应类:
public class Car {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
方便测试:创建有参构造函数
public Car(String name){
this.name = name;
}
2. 静态工厂方法的定义
public class StaticBeansFactory {
private static Map<String,Car> cars= new HashMap<>();
static {
cars.put("baoma",new Car("baoma"));
cars.put("aodi",new Car("aodi"));
}
静态方法
public static Car getCar(String name){
return cars.get(name);
}
}
测试:
测试静态工厂方法配置bean
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-factory.xml");
Car car = (Car)ctx.getBean("car1");
System.out.println(car); ||获取到aodi 这个Car
通过静态工厂方法:首先要写好相应的静态方法
二:实例工厂方法
即首先要创建工厂的实例,再通过工厂实例获取目标Bean实例
测试代码:
1. 实例工厂
public class InstanceCarFactory {
private Map<String,Car> cars = null;
public InstanceCarFactory(){
cars= new HashMap<>();
cars.put("aodi",new Car("aodi"));
cars.put("dazhong",new Car("dazhong"));
}
public Car getCar(String name){
return cars.get(name);
}
}
2. XML配置文件
1. 配置工厂实例
<bean id="carFactory" class="spring.beans_factory.InstanceCarFactory"></bean>
2. 配置目标Bean实例
<!--使用工厂实例的方法获取目标Bean 实例-->
<bean id="car2" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="dazhong"></constructor-arg>
</bean>
总结:
工厂方法就是在工厂中完成实例的配置,定义一个获取的方法,在配置文件中通过相应的获获取方法配置目标Bean(在配置文件中将目标对象交给IOC容器(Bean))
三:FactoryBean
FactoryBean 是Spring提供给我们的一个组件(interface)
测试代码:
1. factoryBean implement FactoryBean
public class CarFactoryBean implements FactoryBean<Car> {
//定义一个属性
private String type ;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
// 返回Bean
@Override
public Car getObject() throws Exception {
return new Car(type);
}
//返回bean 的类型
@Override
public Class<?> getObjectType() {
return Car.class;
}
//是否为单例
@Override
public boolean isSingleton() {
return true;
}
}
2. xml 配置文件
<!--测试FactoryBean 配置Bean-->
<bean id="car" class="spring.factorybean.CarFactoryBean">
<!--如果factoryBean 中定义了属性也可以配置属性,<>property-->
<property name="type" value="BMW"></property>
</bean>
3. 测试
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-factoryBean.xml");
Car car = (Car)ctx.getBean("car");
System.out.println(car);
4. 测试结果
Car{name='BMW'}
FactoryBean 配置适用于目标Bean中依赖了其他Bean的情况
以上配置方式都是基于XML配置文件的方式
PART TWO 通过注解配置Bean
通过注解配置Bean是更加常用的方式
一:将Bean添加到IOC容器中
- 组建扫描
Spring从ClassPath 自动扫描,侦测,实例化具有特定注解的类将其添加到IOC容器中进行管理-----变为组件
特定的注解:
1. @Component : 基本注解,标识了一个受Spring管理的组件
2. @Repository:标识了持久层组件
3. @Service : 标识了业务层组件
4. @Controller :标识了表现层组件
其实对于Spring来说这几个注解都是一样的,都标识了一个受Spring管理的组件,只是对于开发人员,为了项目的结构清晰,用单词将他们区分
对于扫描到的组件,Spring 的默认起名:类名的第一个字母小写,也可以通过注解的value 属性由开发人员自定义组件的名字
在配置文件中要配置扫描:< context:component-sacn >
2. < context:component-sacn > 配置
< context:component-sacn >
中的属性和子节点对扫描加以限制
1.属性: base-package=“包的全限定名” : Spring会扫描包下所有的包和子包。
1. 两个属性
2.两个子节点
通过这四个的设置,对扫描的包进行限制
二:实例之间相互存在依赖的Bean配置
通过注解实现Bean与Bean之间的依赖关系
< context:component-sacn > 配置元素会自动注册AutowireAnnotationBeanPostProcessor 实例(后置处理器),该实例可以自动装配具有@Autowired , @resource @Inject 注解属性
也就是说,通过< context:component-sacn > 配置的Bean ,可以在bean 中直接使用@Autowired @Resource @ Inject 注入它所依赖的Bean实例
使用@Autowired 自动装配Bean:根据类的类型匹配
-
普通字段,一切有参数的方法上都可以应用@Autowired 都可以使用该注解;
但是如果注入的Bean 在IOC容器中没有就会 抛出异常。
-
如果某一属性
允许不被被设置(允许IOC 容器中没有该Bean)可以 将@Autowired 的required 属性设置为false
,这样就不会报 -
如果IOC容器中有
多个符合的Bean(类型符合),会根据Bean的名字和匹配的属性名去匹配
;如果出现一个注入IOC容器中存在多个 Bean,就会抛出异常 -
出现上述问题的解决办法(有多个类型符合的Bean,但是没有与配置的属性名义一致的Bean):在配置Bean的时候就
给默认命名一样的Bean起不一样的名字/和属性名或者字段名一致
;或者在注入的时候指定注入哪一个Bean 注解@Qualifier("Bean 的名字") 配置指定的Bean
-
(了解) @Autowired 在数组上面,会将所有符合的Bean全部装配;在集合上面会见所有兼容的Bean全部装配,在Map上面Bean的名称为键,Bean实例为值
@Resource 和@Inject 和@Autowired 的用法类似,一般都使用@Autowired
三:spring 4.x 中的新特性 泛型注入
两个具有泛型类之间 互相存在引用关系,这样的依赖将会被子类继承
代码实例:
泛型类1.
class BaseRepository<T>{}
泛型类2.
class BaseService<T>{
@Autowire
private BaseRepository<T> repository;
public void test(){
System.out.printf(repository);
}
}
子类1.
@Repository
class UserRepository extends Baserepository<User>{}
子类2.
@Service
class UserService extends BaseService<User>{}
测试:
UserService userService = new UserService();
userService.test();
结果打印的是UserRepository