一 说明
现在开发比较流行springboot,但很多开发人员都忽略l了springboot是基于spring而衍生的子项目,不懂spring如何玩转springboot?难道就靠几天的培训跟文章就能玩转springboot了么?答案肯定是不行的,要深入了解springboot必须要会spring,基础很重要,重要的话再怎么说都不为过;作者写spring的基础文章和概念性的理解还有一个很重要的目的,那就是为后面的分析源码做准备,如果一下子就上源码,我相信很多人都会被绕进去,都不知道回事,所以老老实实的学习才是技术提升的必经之路。有兴趣的开发人员或者学生可以关注我的sping专栏。
二 bean 简介
由于之前的文章已经讲过beans包和核心概念就不赘述。spring IOC container 可以容纳一个或者多个beans,beans的是随着 configuration metadata 的提供而创建的,configuration metadata 之前文章也提过,其最原始的配置方式就xml.
这些bean的定义其实就是对应BeanDefinition Object。下面源码一句话;BeanDefinition(接口) 就是 bean的一个实例,其有属性值,构造参数值和更深层次的信息,这些由其具体的实现者提供。
A BeanDefinition describes a bean instance, which has property values,constructor argument values,
and further information supplied by
concrete implementations.
BeanDefinition 的 元数据举例:
- bean的声明周期和作用域(scop,lifecycle callbacks)
- 包限定的类名:通常就是真实类的全类名
- 在container直接的相互协作依赖。
- 在创建对象的时候配置其他信息,比如使用bean管理连接池,限值连接池的大小等。
通常元数据就是转为属性:
- class (bean全类名)
- name (bean的名称)
- scope (作用域)
- constructor arguments (构造器参数)
- properties (属性)
- autowiring mode (自动配置模式)
- lazy-initialization mode (懒初始化模式)
- initialization method (bean初始化方法)
- destruction method (bean摧毁方法)
此外还可以通过 ApplicationContext 的实现者(比如使用getBeanFactory()获得DefaultListableBeanFactory)通过registerSingleton方法和registerBeanDefinition方法去配置元数据,但这种方式不常见,通常都是使用xml
三 bean的命名
每一个bean通常都是有一个或者多个身份,使用bean的别名等,但是container在管理bean时其必须要有唯一标识。通常基于xml配置元数据,<bean>
元素的 id , name 属性通常就代表了一个bean的唯一标识。命名的规则是第一个字母小写后面的字母或者数字使用驼峰比如 userDao
, userService
。通常 不指定 bean的名称也是可以,spring container 会自动给bean生成一个唯一标识,但是,如果要按名称引用该bean,则必须通过使用ref元素或 Service Locator 样式查找提供名称。
四 别名
通常在大型的项目中会使用到别名,比如主系统和子系统集成的时候 一个bean在相同的container中称为fromName,使用别名后就会指向toName,示例如下:
<alias name="fromName" alias="toName"/>
五 bean的实例化
bean的实例化方式其实可以分为三种,第一种就是直接使用bean元素,container初始化后,直接拿到bean的实例,这跟平时new 对象没啥区别,但是默认情况下由container的bean实例化后拿到的实例都是单例。第二种就是使用static factory-method
,(静态工厂模式)。第三种就是 factory-method
(实例工厂模式)。第二种和第三种这两种方式不是很常见,container在初始化的时候会调用fatory-method实例化bean,fatory-method会去工厂中调用创建实例的方法(createInstance)。
区别是否是内部类通常使用$区分,比如 com.youku1327. Animal$$dog
5.1 使用构造器的方式实例化bean
示例如下,有使用spring框架开发的人员肯定很熟悉,我们经常使用这种方式实例化bean
<bean id="iocService" class="com.youku1327.ioc.service.IocService">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
5.2 使用 static factory method 实例化bean
静态工厂 如下,本示例的fatory-method的静态工厂就是其本身(你也可以 new 其他的实例放进静态工厂里面),但是 其声明方法类型必须是static。
/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/10/31 13:55
*/
public class StaticBeanService {
private static StaticBeanService staticBeanService = new StaticBeanService();
// other properties
private StaticBeanService() {}
public static StaticBeanService createInstance() {
// add your properties
return staticBeanService;
}
}
配置如下:
<?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">
<!-- static factory method services -->
<bean id="staticBeanService" class="com.youku1327.bean.entity.StaticBeanService" factory-method="createInstance">
</bean>
</beans>
5.3 使用 instance factory method 实例化bean
实例化工厂模式和静态工厂模式很相似,区别在于创建实例的方法有没有使用static关键字而已。本实例的Car其实应该是接口,然后通过具体的实现类(比如兰博基尼Car,宝马car等)实现接口,然后在Carfactory中使用相应的createCarInstance方法,在xml中配置对应的bean即可。简单的实现示例如下:
实体如下:
/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/10/31 14:58
*/
public class Car {
private String carName;
private String color;
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
实例化工厂如下:
/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/10/31 15:00
*/
public class CarFactory {
private static Car car = new Car();
private CarFactory(){
}
public Car createCarInstance(){
return car;
}
}
配置如下:
<?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">
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="carFactory" class="com.youku1327.bean.factory.CarFactory">
<!-- inject any dependencies required by this locator bean -->
</bean>
<!-- the bean to be created via the factory bean -->
<bean id="car" factory-bean="carFactory" factory-method="createCarInstance"/>
</beans>
六 参考文档
【本文github源码在公众号文章末尾链接】。