撸一撸Spring Framework-IoC-BeanFactory

BeanFactory是Spring IoC中最核心的接口,它承担IoC最基本的职责,即创建并管理各种类的对象。BeanFactory接口的关键方法getBean的实现中,会试图从缓存中查找并返回对应的bean,若不存在,则根据bean对应的bean definition来创建bean(包括实例化、属性赋值、依赖装配、初始化等工作,这部分工序加上bean的销毁,被通称为bean的生命周期),然后缓存下来,因此得名bean工厂

容器启动时,BeanFactory会从配置元信息中加载beanDefinition,之后的bean创建和管理工作都依赖于beanDefinition

配置元信息:包括xml文件、java configuration+注解两种形式,BeanFactory只支持前者,后者属于ApplicationContext的能力

beanDefinition:每个bean都来源于一个beanDefinition,它定义了bean的类名、构造器参数值、属性值、对其他bean的引用关系、scope等信息

BeanFactory只定义了最基础的IOC容器功能,它的扩展接口众多,继承体系设计优雅,堪称经典:

ListableBeanFactory:有时候一个class会对应多个bean,如果试图通过BeanFactory获取这多个bean,只能按beanName逐个查找

listable表示可列举的、可枚举的,它支持枚举同一个class对应的所有bean实例,比如方法Map<String, T> getBeansOfType(Class<T> type)返回1个包含了指定class所有bean的map(key为beanName,value为bean),我们可以用@Autowired List<T> xx、@Autowired Map<String,T> xx注入T类型对应的所有bean,正是得益于此

HierarchicalBeanFactory:hierarchical表示层次性的,它允许BeanFactory设置一个parent BeanFactory,在查找bean时,会首先委托给parent BeanFactory,如果没找到,再从当前BeanFactory查找,也就是父BeanFactory中的bean对子BeanFactory可见,反之不可见。我们熟知的父子容器,就是依赖于这一机制,它使得每个容器可以关注一个特定的层,实现关注点分离,比如在Spring MVC中,业务层和持久层位于父容器中,展现层位于子容器中,这样展现层可以引用业务层、持久层的bean,反之则不可以

AutowireCapableBeanFactory:autowire capable表示具有自动装配能力的,是针对外部对象来说的(不归spring管理的对象),比如你想自行控制一个类的创建工作,而非交给spring,但是你又想在类中使用spring中的bean,就可以这样操作:

package com.example.spring;
import org.springframework.stereotype.Component;

//spring管理的类
@Component
public class SpringManagedService {
}
<!---------------------------分割线----------------------------!>

package com.example.spring;
import org.springframework.beans.factory.annotation.Autowired;

//不归Spring管理的类
public class MyService {
    @Autowired
    private SpringManagedService springManagedService;

    @Override
    public String toString() {
        return "MyService{" +
                "springManagedService=" + springManagedService +
                '}';
    }
}
<!---------------------------分割线----------------------------!>

package com.example.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages ={"com.example.spring"} )
public class AutowireCapableDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();
        applicationContext.register(AutowireCapableDemo.class);
        applicationContext.refresh();

        //自行实例化
        MyService myService=new MyService();
        applicationContext.getAutowireCapableBeanFactory().autowireBean(myService);
        System.out.println(myService.toString());

        applicationContext.close();
    }
}

ConfigurableBeanFactory:configurable表示可配置的,它其中包含了众多的setXX、addXX、registerXX方法使我们可以定制BeanFactory,比如addBeanPostProcessor、registerScope(自定义singleton、prototype之外的scope,比如request、session、application等在web应用中使用的scope)、setApplicationStartup(Spring在容器启动过程中的各个关键步骤,会调用ApplicationStartup#start方法启动、终止一个个的StartupStep(表示一个步骤的开始与结束),可以用于记录一些指标信息,比如记录各阶段耗费的时间)

ConfigurableBeanFactory还继承于SingletonBeanRegistry,SingletonBeanRegistry的核心方法registerSingleton(String beanName, Object singletonObject)允许客户端向BeanFactory中注册一个外部对象(不归spring管理的对象),使之成为spring内部的单例bean,要注意的是该对象应该是已经完整初始化过的,spring不会再对其执行任何与生命周期回调的相关逻辑

DefaultListableBeanFactory:作为上述所有BeanFactory接口的完整实现,它无疑是非常重要的,在众多ApplicationContext实现中,都持有一个DefaultListableBeanFactory引用,所有bean管理的操作都会委托给DefaultListableBeanFactory

同时它还实现了BeanDefinitionRegistry接口,该接口作为beanDefinition注册中心的抽象,提供了beanDefinition的注册、删除、查询、计数等方法 

在Spring容器的启动阶段,从配置元信息中加载到的beanDefinition,会通过registerBeanDefinition方法保存下来(内存中),后续操作直接从中读取。spring还允许开发者在运行时注册新的beanDefinition、或者修改已有的beanDefinition信息,这无疑提高了bean定义机制的灵活性

public class BeanFactoryDemo {

    public static void main(String[] args) {
        //创建一个空的bean工厂
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        //向工厂里添点原材料(beanDefinition),BeanFactory支持两种添加beanDefinition的方式
        //1、从xml中加载
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        //通过ResourceLoader加载resources下的xml资源
        Resource resource = new DefaultResourceLoader().getResource("classpath:bean.xml");
        //从xml资源中读取beanDefinition
        reader.loadBeanDefinitions(resource);

        //2、调用注册api
        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(User.class).getBeanDefinition();
        beanDefinition.getPropertyValues().add("id", "002");
        beanDefinition.getPropertyValues().add("name", "li si");
        beanFactory.registerBeanDefinition("user2", beanDefinition);

        //获取所有User类型的bean
        Map<String, User> userMap = beanFactory.getBeansOfType(User.class);
        //输出-->{user1=User{id='001', name='zhang san'}, user2=User{id='002', name='li si'}}
        System.out.println(userMap);
    }
}

public class User{
    private String id;
    private String name;

    public User(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public User() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
## resources/demo.xml
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id="user1" class="com.example.spring.entity.User" >
      <property name="id" value="001"/>
      <property name="name" value="zhang san"/>
   </bean>
</beans>

猜你喜欢

转载自blog.csdn.net/wb_snail/article/details/121185678