Spring容器和Bean


BeanFactory

它是ApplicationContext的父接口

它才是Spring的核心容器,主要的ApplicationContext的实现都组合了它的功能

使用ApplicationContext的getBean方法,实际上先拿到BeanFactory对象,再去调用BeanFactory的getBean方法

BeanFactory表面上只有getBean功能实际上,控制反转,基本的依赖注入,直至Bean的生命周期都是由它的实现类提供

ApplicationContext功能

  • MessageSource:处理国际化资源的能力(翻译) 比如 getMessage方法

  • RessourcePatternResolver:通配符匹配资源的能力 比如 getResources方法
//表示在resources目录下的META-INF子目录下的spring.factories文件和jar包内的......
//*号表示也可以jar内进行搜索
Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource : resources) {
    System.out.println(resource);
}
  • ApplicationEventPublisher:发布事件能力 比如 publishEvent方法
//获取Component1然后进行注册
context.getBean(Component1.class).register();

//在Component1中进行声明
private static final Logger log = LoggerFactory.getLogger(Component1.class);
//该容器对象具备发送事件的功能
@Autowired
private ApplicationEventPublisher context;	//事件发生器
public void register() {
    log.debug("用户注册");
    context.publishEvent(new UserRegisteredEvent(this));
}

//在Component2中监听该事件
private static final Logger log = LoggerFactory.getLogger(Component2.class);
@EventListener
public void aaa(UserRegisteredEvent event) {
    log.debug("{}", event);
    log.debug("发送短信");
}
  • EnvironmentCapable:读取环境信息 比如getProperty方法
//获取properties文件和系统环境变量对应键的值
System.out.println(context.getEnvironment().getProperty("java_home"));
System.out.println(context.getEnvironment().getProperty("server.port"));

BeanFactory的实现

给Bean添加定义并进行注册

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(class, scope, 初始化, 销毁)
AbstractBeanDefinition beanDefinition =
        BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
//注册
beanFactory.registerBeanDefinition("config", beanDefinition);

添加 BeanFactory 后处理器

// 给 BeanFactory 添加一些常用的后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

//如果只是添加后处理器不进行扩展,则无法解析@Confident和@bean注解

// BeanFactory 后处理器主要功能,补充了一些 bean 定义
// getBeansOfType 根据类型获取多个bean(bean后处理器)
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
    beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);   //执行beanFactory 后处理器
});

@Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {return new Bean1();}
        @Bean
        public Bean2 bean2() {return new Bean2();}
        @Bean
        public Bean3 bean3() {return new Bean3();}
        @Bean
        public Bean4 bean4() {return new Bean4();}
    }
    interface Inter { }
    static class Bean3 implements Inter { }
    static class Bean4 implements Inter { }
    static class Bean1 {
        private static final Logger log = LoggerFactory.getLogger(Bean1.class);
        public Bean1() {
            log.debug("构造 Bean1()");
        }
        @Autowired
        private Bean2 bean2;
        public Bean2 getBean2() {return bean2;}
        //同时添加两个注解(后处理器的顺序决定了哪个先被解析)
        @Autowired
        @Resource(name = "bean4")
        private Inter bean3;
        public Inter getInter() {return bean3;}}
    static class Bean2 {
        private static final Logger log = LoggerFactory.getLogger(Bean2.class);
        public Bean2() {
            log.debug("构造 Bean2()");
        }
    }

添加 Bean 后处理器

// Bean 后处理器, 针对 bean 的生命周期的各个阶段提供扩展, 例如 @Autowired @Resource ...
beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
        .forEach(beanPostProcessor -> {
    beanFactory.addBeanPostProcessor(beanPostProcessor);    //建立Bean工厂和后处理器的关系
});

后处理器器顺序

//默认是Common的后处理器排在前面,Autowired的排在后面
System.out.println("Common:" + (Ordered.LOWEST_PRECEDENCE - 3));
System.out.println("Autowired:" + (Ordered.LOWEST_PRECEDENCE - 2));

总结

BeanFactory总结:

  • 不会主动调用 BeanFactory 后处理器
  • 不会主动添加 Bean 后处理器
  • 不会主动初始化单例
  • 不会解析beanFactory 还不会解析 ${ } 与 #{ }

Bean后处理器会有排序的逻辑

ApplicationContext的实现

ClassPathXmlApplicationContext

在类路径下读取XML配置文件

private static void testClassPathXmlApplicationContext() {
    ClassPathXmlApplicationContext context =
            new ClassPathXmlApplicationContext("a02.xml");
    for (String name : context.getBeanDefinitionNames()) {
        System.out.println(name);
    }
    System.out.println(context.getBean(Bean2.class).getBean1());
    /**	
     *  结果:
     *	bean1
     *	bean2
     *	com.itheima.a02.A02$Bean1@6392827e
     */
}
//a02.xml
<!-- 控制反转, 让 bean1和bean2 被 Spring 容器管理 -->
<bean id="bean1" class="com.itheima.a02.A02.Bean1"/>
<bean id="bean2" class="com.itheima.a02.A02.Bean2">
    <!-- 依赖注入, 让 bean2 建立与 bean1 的依赖关系 -->
    <property name="bean1" ref="bean1"/>
</bean>

FileSystemXmlApplicationContext

在磁盘路径下读取XML配置文件

private static void testFileSystemXmlApplicationContext() {
    FileSystemXmlApplicationContext context =
            new FileSystemXmlApplicationContext("src\\main\\resources\\a02.xml");
}

AnnotationConfigApplicationContext

基于java配置类来完成

一种是指定java文件配置类,另一种是指定扫描路径

private static void testAnnotationConfigApplicationContext() {
    AnnotationConfigApplicationContext context =
            new AnnotationConfigApplicationContext(Config.class);
}

@Configuration
static class Config {
    @Bean
    public Bean1 bean1() {return new Bean1();}
    @Bean
    public Bean2 bean2(Bean1 bean1) {
        Bean2 bean2 = new Bean2();
        bean2.setBean1(bean1);
        return bean2;
    }
}
static class Bean1 { }
static class Bean2 {
    private Bean1 bean1;
    public void setBean1(Bean1 bean1) {
        this.bean1 = bean1;
    }
    public Bean1 getBean1() {
        return bean1;
    }
}

AnnotationConfigServletWebServerApplicationContext

基于 java 配置类来创建,用于 web 环境

private static void testAnnotationConfigServletWebServerApplicationContext() {
    AnnotationConfigServletWebServerApplicationContext context =
            new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
    for (String name : context.getBeanDefinitionNames()) {
        System.out.println(name);
    }
}
@Configuration
static class WebConfig {
    @Bean   //产生内嵌的 tomcat 容器
    public ServletWebServerFactory servletWebServerFactory(){return new TomcatServletWebServerFactory();}
    @Bean   //创建 dispatcherServlet 对象
    public DispatcherServlet dispatcherServlet() {return new DispatcherServlet();}
    @Bean   //将 dispatcherServlet 注册到tomcat容器中
    public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
        return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
    }
    @Bean("/hello")
    public Controller controller1() {
        return (request, response) -> {
            response.getWriter().print("hello");
            return null;
        };
    }
}

Bean的生命周期

在各个阶段里都会有由bean后处理器提供的功能增强

bean的后处理器

创建前后的增强

  • postProcessBeforeInstantiation
    • 这里返回的对象若不为 null 会替换掉原本的 bean,并且仅会走 postProcessAfterInitialization 流程
  • postProcessAfterInstantiation
    • 这里如果返回 false 会跳过依赖注入阶段

依赖注入前的增强

  • postProcessProperties
    • 如 @Autowired、@Value、@Resource

初始化前后的增强

  • postProcessBeforeInitialization
    • 这里返回的对象会替换掉原本的 bean
    • 如 @PostConstruct、@ConfigurationProperties
  • postProcessAfterInitialization
    • 这里返回的对象会替换掉原本的 bean
    • 如代理增强

销毁之前的增强

  • postProcessBeforeDestruction
    • 如 @PreDestroy
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {

    private static final Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);

    //postProcessBeforeDestruction:在销毁之前执行 bean 后处理器
    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean"))
            log.debug("<<<<<< 销毁之前执行, 如 @PreDestroy");
    }

    //postProcessBeforeInstantiation:在实例化之前执行
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean"))
            log.debug("<<<<<< 实例化之前执行, 这里返回的对象会替换掉原本的 bean");
        return null;
    }

    //postProcessAfterInstantiation:实例化之后执行,如果返回 false 会跳过依赖注入阶段,返回true则不会跳过
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<< 实例化之后执行");
        }
        return true;
    }

    //postProcessProperties:依赖注入阶段执行
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean"))
            log.debug("<<<<<< 依赖注入阶段执行, 如 @Autowired、@Value、@Resource");
        return pvs;
    }

    //postProcessBeforeInitialization:初始化之前执行
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean"))
            log.debug("<<<<<< 初始化之前执行, 这里返回的对象会替换掉原本的 bean, 如 @PostConstruct、@ConfigurationProperties");
        return bean;
    }

    //postProcessAfterInitialization:初始化之后执行
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean"))
            log.debug("<<<<<< 初始化之后执行, 这里返回的对象会替换掉原本的 bean, 如代理增强");
        return bean;
    }
}

模板方法设计模式

public static void main(String[] args) {
    MyBeanFactory beanFactory = new MyBeanFactory();
    beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired"));
    beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource"));
    beanFactory.getBean();
}

static class MyBeanFactory {
    public Object getBean() {
        Object bean = new Object();
        System.out.println("构造 " + bean);
        System.out.println("依赖注入 " + bean); // @Autowired, @Resource
        for (BeanPostProcessor processor : processors) {
            processor.inject(bean);
        }
        System.out.println("初始化 " + bean);
        return bean;
    }
    private List<BeanPostProcessor> processors = new ArrayList<>(); //后处理器集合
    public void addBeanPostProcessor(BeanPostProcessor processor) {processors.add(processor);}
}

static interface BeanPostProcessor {
    public void inject(Object bean); // 对依赖注入阶段的扩展
}

容器与Bean


  目录