BeanFactory能做哪些事?

深入学习Spring

1.到底什么是BeanFactory

- 他是ApplicationContext 的父接口

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

ApplicationContext实际上是继承的BeanFactory是一个子接口,对一些方法进行了组合扩展

ConfigurableApplicationContext context = SpringApplication.run(FrameApplication.class, args);

返回结果是Spring的容器

2. BeanFactory 能干点啥

-表面上只有 getBean

-实际上控制反转,基本的依赖注入,直至Bean的生命周期的各种功能,都是由他实现

主要的实现类是:DefaultListableBeanFactory 这个实现类有许多的方法

        //启动 Spring 应用程序上下文:
        ConfigurableApplicationContext context = SpringApplication.run(FrameApplication.class, args);
        //获取 singletonObjects 字段:
        Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        //设置为可访问的状态
        singletonObjects.setAccessible(true);
        //获取 BeanFactory 并获取 singletonObjects 的值
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //过滤和打印以 "component" 开头的单例对象:
        Map<String,Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
        map.entrySet().stream().filter(e->e.getKey().startsWith("component"))
                .forEach(e->{
                    System.out.println(e.getKey() + "=" + e.getValue());
        });

3.Application功能

扩展的三个方法

ResourcePatternResolver:ResourcePatternResolver是 Spring 框架提供的一个接口,它扩展了 org.springframework.core.io.ResourceLoader 接口,用于解析资源模式匹配的资源。通过ResourcePatternResolver你可以使用 Ant 风格的路径模式来查找类路径下的资源文件,例如查找所有以 .xml 结尾的文件或者特定目录下的所有文件等。

ApplicationEventPublisher:是 Spring 框架中的一个接口,用于发布应用程序事件(Application Event)。Spring 的事件机制允许不同部分的代码(如组件、服务、控制器等)在特定条件下发布事件,而订阅者可以监听这些事件并作出响应。

EnvironmentCapable:在你的代码中,如果一个类实现了 EnvironmentCapable 接口,那么它就能够获取到当前的 Environment 对象,进而可以根据需要进行配置的读取、属性的访问等操作。

获取资源

        //获取资源 classpath: 类路径下 file: 磁盘路径下
        Resource[] resources = context.getResources("classpath:application.yml");
        for (Resource resource : resources) {
            System.out.println("resource = " + resource);
        }

*代表去jar包中获取 

        Resource[] resourcesMETA = context.getResources("classpath*:META-INF/spring.factories");
        for (Resource resource : resourcesMETA) {
            System.out.println("resource = " + resource);
        }

获取配置

//获取配置
String javaHome = context.getEnvironment().getProperty("java_home");
System.out.println("javaHome = " + javaHome);
String port = context.getEnvironment().getProperty("server.port");
System.out.println("port = " + port);

发送消息:  监听者模式

创建实体类继承:ApplicationEvent 接口

public class UserRegisteredEvent extends ApplicationEvent {
    public UserRegisteredEvent(Object source) { //source 事件源 是谁发的
        super(source);
    }
}

创建两个对象交给Spring进行管理

实现发送消息

@Component
@Log4j2
public class Component1 {
    
    @Autowired
    private ApplicationEventPublisher publisher;

     public void register(){
         log.info("用户注册");
         System.out.println("publisher = " + publisher);
         publisher.publishEvent(new UserRegisteredEvent(this));
     }
}

实现接受消息

@Component
@Log4j2
public class Component2 {

    @EventListener
    public void recipient(UserRegisteredEvent event){
        log.debug("{}",event);
        System.out.println("event = " + event);
        log.debug("发生短信");
        System.out.println("发生短信");
    }
}

启动类获取Bean并且调用方法:

   ConfigurableApplicationContext context = SpringApplication.run(FrameApplication.class, args); 
context.getBean(Component1.class).register();

容器实现:

  • BeanFactory实现的特点
  • ApplicationContext的常见实现和用法
  • 内嵌容器,注册DispatcherSerclet

Bean工厂的功能本质不是很丰富,很多是后处理器去解决的

@Log4j2
public class TestBeanFactory {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean的定义(class ,scope , 初始化 ,销毁)
        AbstractBeanDefinition beanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config",beanDefinition);

        //后置处理器用于处理  @Configuration 下面的子类 中的 @Bean
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);


        //BeanFactory 获取所有同类型的bean 本质是一个Map
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(beanFactoryPostProcessor ->
                beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));

        // Bean 后处理器 ,针对bean的生命周期的各个阶段提供扩展,例如  @Autowired    @Resource

        beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
                .sorted(beanFactory.getDependencyComparator())  //进行bean的排序
                .forEach(beanPostProcessor -> {
            System.out.println("beanPostProcessor = " + beanPostProcessor);
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        });

        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println("name = " + name);
        }
        //提前整备好单例 等到使用直接去拿
        beanFactory.preInstantiateSingletons();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>");
        //默认延迟实例化
//        System.out.println(beanFactory.getBean(Bean1.class).getBean2());
        //设置成指定名字 才能成功
        System.out.println(beanFactory.getBean(Bean1.class).getInter());
    }

    @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 {
        public void a();
    }
    static class Bean3 implements Inter {
        @Override
        public void a() {
            System.out.println("Bean3()");
        }
    }

    static class Bean4 implements Inter {
        @Override
        public void a() {
            System.out.println("Bean4()");
        }
    }


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

       @Autowired   //先生效
        @Resource(name = "bean4")  //这里可以指定名字注入
       private Inter bean3;

        public Inter getInter(){
            return bean3;
        }

        public Bean2 getBean2(){
           return bean2;
       }
    }

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

学会了什么:

beanFactory 不会做的事

  1. 不会主动调用BeanFactory 后处理器
  2. 不会主动添加Bean后处理器
  3. 不会主动初始化单例
  4. 不会解析beanFactory 还不会解析¥{ } 和#{ }
  5. bean后处理器会有排序的逻辑

解析 :这个类AutowiredAnnotationBeanPostProcessor是解析 @Autowired

CommonAnnotationBeanPostProcessor 是解析@Resource注解的

AutowiredAnnotationBeanPostProcessor源码中设置order的优先级主要是order实现的值越小优先级越高,

其中@Autowired的优先级比@Resource优先级高,是order的大了1 ,可以使用Stream流进行排序将两个bean添加到容器中加了排序以后@Resource 比@Autowired 的优先级高了

ApplicationContext的学习

public class TestSApplication {
    public static void main(String[] args) {
//        testAnnotationConfigApplicationContext();
        testAnnotationConfigServletWebServerApplicationContext();
    }


    public static void testAnnotationConfigApplicationContext(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(config.class);
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println("name = " + name);
        }
        System.out.println(context.getBean(Bean2.class).getBean1());
    }

    public static void testAnnotationConfigServletWebServerApplicationContext(){
        AnnotationConfigServletWebServerApplicationContext context =
                new AnnotationConfigServletWebServerApplicationContext(webConfig.class);
    }

    @Configuration
    static class webConfig{
        //注入启动一个 Tomcat
         @Bean
         public ServletWebServerFactory servletWebServerFactory(){
             return new TomcatServletWebServerFactory();
         }
         //注入前端控制器
        @Bean
        public DispatcherServlet dispatcherServlet(){
            return new DispatcherServlet();
        }
        //DispatcherServlet 放入到指定的路径中
        @Bean
        public DispatcherServletRegistrationBean registrationBean( DispatcherServlet dispatcherServlet){
            return new DispatcherServletRegistrationBean(dispatcherServlet,"/");
        }
        //实现一个Controller的接口 可以用作浏览器的访问
        @Bean("/hello")
        public Controller controller1(){
            return (request, response) -> {
                response.getWriter().print("hello");
                return null;
            };
        }
    }


    @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{
        public Bean1 bean1;

        public Bean1 getBean1() {
            return bean1;
        }

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

学到了什么:

常见的ApplicationContext 容器实现

内嵌容器 DispatcherServlet 的创建方法 作用

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值