• Spring高级


    BeanFactory与ApplicationContext

    到底什么是BeanFactory
    1.他是ApplicationContext的父接口
    2.他才是Spring的核心容器,主要的ApplicationContext实现都组合了它的功能
    3.ctrl+alt+u看一下关系图在这里插入图片描述
    看一下BeanFactory
    1.ctrl+f12看一下方法
    在这里插入图片描述在这里插入图片描述

    2.可以看到BeanFactory没有特别多常用的方法,这里我们要认识到实际上一些功能,控制反转、依赖注入、直到Bean的生命周期等功能都是由BeanFactory的实现类提供的

    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) {
           //引导类中的context就是我们的spring容器
            ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
            System.out.println(context);
            Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
            singletonObjects.setAccessible(true);
            ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
            Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
            map.forEach((k, v) -> {
                System.out.println(k + "=" +v);
            });
        }
    }
    

    ApplicationContext功能

    MessageSource翻译国际化:

    在这里插入图片描述

    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) throws Exception {
            //引导类中的context就是我们的spring容器
            ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
            //可以从配置的翻译文本中读取不同的翻译信息,web开发时中文或者英文条件从浏览器的请求头中携带过来
            context.getMessage("hello", null, Locale.CHINA);//输出hello
            context.getMessage("hello", null, Locale.ENGLISH);//输出你好
        }
    
    }
    

    ResourcePatternResolver

    获取源路径这里是引用

    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) throws Exception {
            //引导类中的context就是我们的spring容器
            ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
            //可以从配置的翻译文本中读取不同的翻译信息
            Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
            for (Resource resource : resources) {
                System.out.println(resource);
            }
        }
    
    }
    

    获取环境变量信息EnvironmentCapable:

    在这里插入图片描述

    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) throws Exception {
            //引导类中的context就是我们的spring容器
            ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
            System.out.println(context.getEnvironment().getProperty("spring.messages.basename"));
        }
    
    }
    

    事件发布器ApplicationEventPublisher:

    这里是引用
    在这里插入图片描述
    定义事件

    import org.springframework.context.ApplicationEvent;
    public class StudentRegisteredEvent extends ApplicationEvent {
        public StudentRegisteredEvent(Object source) {
            super(source);
        }
        @Override
        public String toString() {
            return super.toString();
        }
    }
    

    发布事件

    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) throws Exception {
            //引导类中的context就是我们的spring容器
            ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
            context.publishEvent(new StudentRegisteredEvent(123));
        }
    }
    

    接收事件

    import com.rlw.demo.event.StudentRegisteredEvent;
    import org.springframework.context.event.EventListener;
    import org.springframework.stereotype.Service;
    @Service
    public class StudentService {
        @EventListener
        public void ask(StudentRegisteredEvent event){
            System.out.println(event);
        }
    }
    

    容器实现

    BeanFactory实现的特点:beanFactory不会帮我们主动调用beanFactory的后处理器,也不会主动帮助我们调用bean的后处理器,也不会初始化单例,也不会解析${}、#{},所以ApplicationContext都帮助我们做了,接下来看ApplicationContext

    package com.rlw.demo.TestBean;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.beans.factory.support.AbstractBeanDefinition;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.context.annotation.AnnotationConfigUtils;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    public class TestBeanFactory {
        public static void main(String[] args) {
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    
            //bean的定义(class, scope, 初始化, 销毁)
            AbstractBeanDefinition singleton =
                    BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
            beanFactory.registerBeanDefinition("config", singleton);
            //给BeanFactory添加一些常用的后处理器
            AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
    //        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
    //            System.out.println(beanDefinitionName);
            /**
             * 还需要让这些后处理器去工作,不然不会解析config下的bean1,bean2
             *         config
             *         org.springframework.context.annotation.internalConfigurationAnnotationProcessor
             *         org.springframework.context.annotation.internalAutowiredAnnotationProcessor
             *         org.springframework.context.annotation.internalCommonAnnotationProcessor
             *         org.springframework.context.event.internalEventListenerProcessor
             *         org.springframework.context.event.internalEventListenerFactory
             */
    //        }
             //beanFactory后处理器主要功能,补充了一些bean定义
             beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(postProcessor -> { postProcessor.postProcessBeanFactory(beanFactory); });
            for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
                System.out.println(beanDefinitionName);
                /**
                 * config
                 * org.springframework.context.annotation.internalConfigurationAnnotationProcessor   ->解析@Configuration的后处理器
                 * org.springframework.context.annotation.internalAutowiredAnnotationProcessor       ->解析@Autowired的后处理器
                 * org.springframework.context.annotation.internalCommonAnnotationProcessor          ->解析@Resource的后处理器
                 * org.springframework.context.event.internalEventListenerProcessor                  ->
                 * org.springframework.context.event.internalEventListenerFactory
                 * bean1
                 * bean2
                 */
            }
    //        System.out.println(beanFactory.getBean(Bean1.class).getBean2() + "扩展bean处理器前"); //输出null
            //Bean后处理器,针对bean的生命周期的各个阶段提供扩展,例如@Autowired @Resource
            beanFactory.preInstantiateSingletons();//提前创建好单例bean,如果没有此行代码,都是懒惰式创建,什么时候用什么时候创建实例,工厂中只是存储了bean的名称
            beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);//假如一个接口存在多个实现类,我们依赖注入这个接口,能否依赖注入成功?答案是一般不行,除非依赖注入的接口名称 == 要注入的实例,或者使用@Qualifier限制,假如依赖注入同时使用了@Resource与@Aotowred,@Aotowred的优先级要高,在添加bean的后处理器代码顺序@Aotowred在前,可以手动调整
            System.out.println(beanFactory.getBean(Bean1.class).getBean2() + "扩展bean处理器后"); //输出bean2对象
        }
    
        @Configuration
        static class Config {
            @Bean
            public Bean1 bean1() {return new Bean1();}
    
            @Bean
            public Bean2 bean2() {
                return new Bean2();
            }
        }
        static class Bean1 {
    
            public Bean1() {
                System.out.println("bean1");
            }
    
            @Autowired
            private Bean2 bean2;
    
            public Bean2 getBean2() {
                return bean2;
            }
        }
    
        static class Bean2 {
            public Bean2() {
                System.out.println("bean2");
            }
        }
    }
    

    ApplicationContext实现:

    通过类路径下的xml的方式去注入bean

    <?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">
    
        <bean id="bean1" class="com.rlw.demo.TestBean.Bean1"></bean>
        <bean id="bean2" class="com.rlw.demo.TestBean.Bean2"></bean>
        //beanfactory的后处理器
        <context:annotation-config/>
    </beans>
    
    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) throws Exception {
            ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext("b01.xml");
            for (String beanDefinitionName : context1.getBeanDefinitionNames()) {
                System.out.println(beanDefinitionName);
            }
        }
    }
    
    
    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) throws Exception {
            FileSystemXmlApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext("D:\\spring29\\src\\main\\resources\\b01.xml");
            for (String beanDefinitionName : fileSystemXmlApplicationContext.getBeanDefinitionNames()) {
                System.out.println(beanDefinitionName);
            }
        }
    }
    

    读取xml的原理,我们都知道ApplicationContext是基于BeanFactory去注入bean的,也就是基于BeanFactory去组合的功能

    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) throws Exception {
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
            System.out.println("读取xml之前");
            for (String name : beanFactory.getBeanDefinitionNames()) {
                System.out.println(name);//输出null
            }
            System.out.println("读取xml之后");
            XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
            reader.loadBeanDefinitions("b01.xml");
            for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
                System.out.println(beanDefinitionName);//输出bean1,bean2
            }
        }
    }
    

    基于java配置类:

    @Configuration
    public class Config2 {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }
    
        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }
    
    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) throws Exception {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config2.class);
            for (String beanDefinitionName : context.getBeanDefinitionNames()) {
                System.out.println(beanDefinitionName);
            }
            /**
             * org.springframework.context.annotation.internalConfigurationAnnotationProcessor
             * org.springframework.context.annotation.internalAutowiredAnnotationProcessor
             * org.springframework.context.annotation.internalCommonAnnotationProcessor
             * org.springframework.context.event.internalEventListenerProcessor
             * org.springframework.context.event.internalEventListenerFactory
             * config2
             * bean1
             * bean2
             */
        }
    }
    

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

    @Configuration
    public class WebConfig {
        @Bean
        public ServletWebServerFactory servletWebServerFactory() {
            return new TomcatServletWebServerFactory();
        }
        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }
        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }
        @Bean("/hello")
        public Controller controller() {
            return ((request, response) -> {
                response.getWriter().printf("hello");
                return null;
            }
            );
        }
    }
    
    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) throws Exception {
            AnnotationConfigServletWebServerApplicationContext annotationConfigServletWebServerApplicationContext = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
        }
    }
    

    Bean的生命周期

    生命周期的各个阶段:在各个阶段都可以使用bean后处理进行相应的增强功能

    @Component
    public class LifeCycleBean {
        public LifeCycleBean() {
            System.out.println("构造方法");
        }
    
        @Autowired
        public void autowired(@Value("${JAVA_HOME}") String name) {
            System.out.println("依赖注入:" + name);
        }
    
        @PostConstruct
        public void init() {
            System.out.println("初始化");
        }
    
        @PreDestroy
        public void destroy(){
            System.out.println("销毁");
        }
    }
    

    构造方法
    依赖注入:C:\Program Files\Java\jdk1.8.0_201
    初始化
    bean1…
    bean2…
    2022-09-30 16:57:53.452 INFO 352996 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ‘’
    2022-09-30 16:57:53.461 INFO 352996 — [ main] com.rlw.demo.A01Application : Started A01Application in 1.993 seconds (JVM running for 2.902)
    2022-09-30 16:57:53.615 INFO 352996 — [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
    销毁

    待续

  • 相关阅读:
    Game theory
    八大排序之归并排序
    特征值和特征向量简单入门
    【pen200-lab】10.11.1.13
    100G以太网光模块解决方案
    TMD,JVM类加载原来是这样的!!!!
    【Golang】Gin处理GET、POST请求
    论文笔记:Frozen Language Model Helps ECG Zero-Shot Learning
    can not remove .unionfs
    SpingMVC请求和响应
  • 原文地址:https://blog.csdn.net/qq_44805043/article/details/127110114