spring bean 的实例化(3)

x33g5p2x  于2021-08-23 转载在 Spring  
字(4.6k)|赞(0)|评价(0)|浏览(363)

一 说明

现在开发比较流行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 的 元数据举例:

  1. bean的声明周期和作用域(scop,lifecycle callbacks)
  2. 包限定的类名:通常就是真实类的全类名
  3. 在container直接的相互协作依赖。
  4. 在创建对象的时候配置其他信息,比如使用bean管理连接池,限值连接池的大小等。

通常元数据就是转为属性

  1. class (bean全类名)
  2. name (bean的名称)
  3. scope (作用域)
  4. constructor arguments (构造器参数)
  5. properties (属性)
  6. autowiring mode (自动配置模式)
  7. lazy-initialization mode (懒初始化模式)
  8. initialization method (bean初始化方法)
  9. 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>

六 参考文档

IOC Container

相关文章