BeanFactory与ApplicationContext

BeanFactory与ApplicationContext

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) throws   Exception {
        ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
        /**
         * 1 . 到底什么是BeanFactory
         *  - 它是ApplicationContext的父接口
         *  - 它才是Spring的核心容器,主要的ApplicationContext都组合了它的功能
         */
        System.out.println(context);

        /**
         * 2. BeanFactory 能干什么
         *  - 表面上只有 getBean
         *  - 实际上控制反转、基本的依赖注入,直至Bean的生命周期的各种功能,都是由它的实现类提供
         */

        Field singletonFactories = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        singletonFactories.setAccessible(true);
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        Map<String,Object> map = (Map<String, Object>) singletonFactories.get(beanFactory);
        System.out.println(map);


        /**
         * 3 . ApplicationContext 比 BeanFactory 多点啥
         *
         */
        // - MessageSource 国际化,通过浏览器请求头带过来(getMessage)
        // - ResourcePatternResolver 获取资源(file,获取磁盘下的资源,classpath,获取类路径下的资源,classpath*,获取类路径和jar包中的资源)
        Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
        for (Resource resource : resources) {
            System.out.println(resource);
        }
        // - PropertyResolver 获取环境变量
        System.out.println(context.getEnvironment().getProperty("java_home"));
        System.out.println(context.getEnvironment().getProperty("server.port"));
        // - ApplicationEventPublisher 发布事件,实现组件之间的解耦
        PublishEvent bean = context.getBean(PublishEvent.class);
        bean.register();

    }
}

发布事件
事件发布

public class UserRegisterEvent extends ApplicationEvent {
    public UserRegisterEvent(Object source) {
        super(source);
    }
}
@Component
public class PublishEvent {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void register(){
        System.err.println("用户注册");
        applicationEventPublisher.publishEvent(new UserRegisterEvent("用户注册事件"));

    }
}

事件监听

@Component
public class ListenerEvent  {

    @EventListener
    public void listener(UserRegisterEvent userRegisterEvent){
        System.err.println("listener "+userRegisterEvent.getSource()+ "   发短信");
    }
}

BeanFactory 的实现DefaultListableBeanFactory

BeanFactory 处理器

public class DefaultListBeanFactoryDemo {
    public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 定义 bean 并注册到 beanFactory
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(BeanConfig.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("beanConfig",beanDefinition);
        // 可以发现 @Configuration @Bean 注解并没有识别
        // 给beanFactory添加 bean工厂后处理器,并执行后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().
                forEach(beanFactoryPostProcessor ->beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));

        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

    }

    @Configuration
    static class BeanConfig{
        @Bean
        public Bean1 bean1(){
            return new Bean1();
        }
        @Bean
        public Bean2 bean2(){
            return new Bean2();
        }
    }

    static class Bean1{
        public Bean1(){
            System.out.println("Bean11111");
        }
    }
    static class Bean2{
        public Bean2(){
            System.out.println("Bean11111");
        }
    }


}

Bean 处理器

public class DefaultListBeanFactoryDemo {
    public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 定义 bean 并注册到 beanFactory
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(BeanConfig.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("beanConfig",beanDefinition);
        // 可以发现 @Configuration @Bean 注解并没有识别
        // 给beanFactory添加后处理器,并执行后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().
                forEach(beanFactoryPostProcessor ->beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));

//        Bean1 bean = beanFactory.getBean(Bean1.class);
//        System.out.println(bean.bean2());
        // 并未识别到 @Autowire 注解 ?

        // Bean 后处理器,针对bean的生命周期的各个阶段提供扩展,例如 @Autowire @Resoure ...
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);

        // 预先把所有的单例对象 加载后好 而不是用到在加载
        beanFactory.preInstantiateSingletons();
        System.out.println(">>>>>>>>>>>>>>>>>");
        Bean1 bean = beanFactory.getBean(Bean1.class);
        bean.bean2();






    }

    @Configuration
    static class BeanConfig{
        @Bean
        public Bean1 bean1(){
            return new Bean1();
        }
        @Bean
        public Bean2 bean2(){
            return new Bean2();
        }
    }

    static class Bean1{
        public Bean1(){
            System.out.println("Bean11111");
        }
        @Autowired
        private Bean2 bean2;

        public Bean2 bean2(){
            return bean2;
        }

    }
    static class Bean2{
        public Bean2(){
            System.out.println("Bean2222");
        }
    }


}

拓展

当一个接口有多个实现类,把接口注入时,既使用@Autowire 也使用 @Resource 是优先使用谁注入?
这个与 Bean 处理器 被运行的先后顺序有关 ,可以控制

get:

a. beanFactory不会做的事

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

b. bean 后处理器会有排序的逻辑

ApplicationContext 实现

package com.zhj;

import com.zhj.demo.DefaultListBeanFactoryDemo;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.rowset.spi.XmlReader;
import java.lang.annotation.Annotation;

public class TestBeanFactory {

    public static void main(String[] args) {
//        testClassPathXmlApplicationContext();
//        testFileSystemXmlApplicationContext();
        /**
         * 上面两个方法的原理
         */
        /**
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        System.out.println("读取之前");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
//        reader.loadBeanDefinitions(new ClassPathResource("b01.xml"));
        reader.loadBeanDefinitions(new FileSystemResource("src/main/resources/b01.xml"));
        System.out.println("读取之后");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
         */
//        testAnnotationConfigApplicationContext(); // 自动配置了后处理器
        testAnnotationConfigServletApplicationContext(); // 运行访问 http://localhost:8080/hello

    }

    static void testClassPathXmlApplicationContext() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("b01.xml");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

    }

    ;

    static void testFileSystemXmlApplicationContext() {
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("src/main/resources/b01.xml");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

    ;

    static void testAnnotationConfigApplicationContext() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
    }

    ;

    static void testAnnotationConfigServletApplicationContext() {
        AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
    }

    @Configuration
    static class WebConfig{
        @Bean
        public ServletWebServerFactory servletWebServerFactory(){
            return new TomcatServletWebServerFactory();
        }
        @Bean
        public DispatcherServlet dispatcherServlet(){
            return new DispatcherServlet();
        }
        @Bean
        public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet){
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        @Bean("/hello") // Controller 是spring提供的一个接口
        public Controller controller(){
            return (httpServletRequest, httpServletResponse) -> {
                httpServletResponse.getWriter().write("hello");
                return null;
            };
        }
    }


    @Configuration
    static class Config{

        @Bean
        public Bean1 bean1(){
            Bean1 bean1 = new Bean1();
            return bean1;
        }
        @Bean
        public Bean2 bean2(Bean1 bean1){
            Bean2 bean2 = new Bean2();
            bean2.setBean1(bean1);
            return bean2;
        }
    }
    static class Bean1{
        public Bean1(){
            System.out.println("111");
        }
    }
    static class Bean2{
        public Bean2(){
            System.out.println("222");
        }
        private Bean1 bean1;

        public void setBean1(Bean1 bean1) {
            this.bean1 = bean1;
        }
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="bean2" class="com.zhj.demo.DefaultListBeanFactoryDemo.Bean2"></bean>
    <bean id="bean1" class="com.zhj.demo.DefaultListBeanFactoryDemo.Bean1">
        <property name="bean2" ref="bean2"></property>
    </bean>
    <!--  添加后处理器  -->
    <context:annotation-config/>
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值