Spring高级49讲笔记-第一讲:容器接口

第一讲:容器接口


学习目标

1.BeanFactory能做那些事

2.ApplicationContext有那些扩展功能

3.事件解耦


一、BeanFactory与ApplicationContext

1.BeanFactory与ApplicationContext以及ConfigurableApplicationContext接口的关系

通过这个类图,我们可以初步的看出来  

ApplicationContext是ConfigurableApplicationContext的父接口

ApplicationContext是间接的继承BeanFactory接口

继承了代表下面的肯定是比上面的接口扩展了一些新的功能的

结论 

到底什么是BeanFactory

  -它是ApplicationContext的父接口
  -它是Spring的核心容器,ApplicationContext 其实是组合了它的功能
即:例如这个getBean(),这个方法ApplicationContext其实调用的还是BeanFactory来进行解决

2.ApplicationContext其实调用的还是BeanFactory来进行解决

 

3.BeanFactory 是ApplicationContext的成员变量

这里可以看出来 beanFactrory的类型其实就是BeanFactory类 ,因此说ApplicationContext是组合了BeanFactory的功能

二、BeanFactory的功能

1.BeanFactory能干点啥

--表面上我们可以看出只有getBean()方法

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

2.BeanFactory其中的实现类---管理单例对象的类DefalutSingletionBeanFatorty

package com.itheima;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.lang.reflect.Field;
import java.util.Map;

/*
* BeanFactory  和 ApplicationContext 的区别
* */
@SpringBootApplication
public class Spring01Application {
    //这个是个日志
    private static  final Logger log=LoggerFactory.getLogger(Spring01Application.class);
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //Spring容器 ---是  ConfigurableApplicationContext 可配置的容器
        ConfigurableApplicationContext context = SpringApplication.run(Spring01Application.class, args);
      
         //获取到DefaultSingletonBeanRegistry --  默认单例Bean注册类中的存放单例对象的map成员变量singletonObjects
        Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        //因为是私有的  ---暴力反射
        singletonObjects.setAccessible(true);
        //获取到对象---  BeanFactory对象
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //通过对象来获取到对应的成员变量 Map集合
        Map<String,Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);

// 传统的Map迭代方式
//        for (Map.Entry<String, Object> entry : map.entrySet()) {
//            System.out.println(entry.getKey() + ":" + entry.getValue());
//        }
// JDK8的迭代方式
//        map.forEach((key, value) -> {
//                    System.out.println(key + ":" + value);
//                }
           
          //迭代map
            map.forEach((k,v)->{
            System.out.println(k+""+v);
        });

    }

}

 结果中我们可以找到所以的单例对象

如果指向要Component这两个对象的话

代码:

 //map.entrySet()获取到key的集合
     //stream().filter  这个是jdk8引入的Stream流(黑马最新基础java有)
     //stream().filter(e-> e.getKey().startsWith("component")) 是进行过滤条件是map的key前面要是component开头的
     //forEach是进行迭代
        map.entrySet().stream().filter(e-> e.getKey().startsWith("component"))
           .forEach(e->{
               System.out.println(e.getKey()+"="+e.getValue());
           });

 结果:

 这里我们就能看出了

--表面上我们可以看出只有getBean()方法

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

我们只是演示了一个实现类 还有很多

三、ApplicationContext的功能

1.四个接口的大致作用

 1.1MessageSource

 

 1.2ResourcePatternResolver

     //classpath:表示在类路径下  jar包下是找不到的  resources文件夹下
        Resource resource = context.getResource("classpath:application.properties");
        System.out.println(resource);
        //classpath*:表示在类路径下和jar包下是找
        Resource[] resource1 = context.getResources("classpath*:META-INF/spring.factories");
        for(Resource resource2 :resource1){
            System.out.println(resource2);
        }

1.3EnvironmentCapable

  //获取系统环境变量  或者properties文件  ---不区分大小写
        System.out.println(context.getEnvironment().getProperty("java_home"));
        System.out.println(context.getEnvironment().getProperty("server.port"));

结果:

1.4ApplicationEventPublisher

事件类

package com.itheima.a01;

import org.springframework.context.ApplicationEvent;

/**
 * @author : wentao
 * @version : 1.0
 * 用户已注册事件
 */
public class UserRegisteredEvent extends ApplicationEvent {
    public UserRegisteredEvent(Object source) {
        super(source);
    }
}

发送事件  

 在上面这个类中写  


 //发送事件
        context.publishEvent(new UserRegisteredEvent(context));

监听事件的类

package com.itheima.a01;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * @author : wentao
 * @version : 1.0
 */
@Component
public class Component2 {
   //这个一个日志  
    private  static  final Logger log=LoggerFactory.getLogger(Component2.class);
    //告诉spring这是一个事件监听的地方
    @EventListener
    //参数就是 发送事件的对象
    public void aaa(UserRegisteredEvent event){
        //方法执行会将这个信息打印到控制台
        log.debug("{}",event);
    }
}

设置一下 application.properties

结果:

 通过这个事件可以实现解耦的功能  

package com.itheima.a01;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

/**
 * @author : wentao
 * @version : 1.0
 */
@Component
public class Component1 {
    private  static  final Logger log=LoggerFactory.getLogger(Component2.class);

    @Autowired
    private ApplicationEventPublisher context;
    public  void register(){
        log.debug("用户注册");

        context.publishEvent(new UserRegisteredEvent(Component1.class));
    }
}
package com.itheima.a01;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * @author : wentao
 * @version : 1.0
 */
@Component
public class Component2 {
    private  static  final Logger log=LoggerFactory.getLogger(Component2.class);
    //告诉spring这是一个事件监听的地方
    @EventListener
    //参数就是 发送事件的对象
    public void aaa(UserRegisteredEvent event){
        log.debug("{}",event);
        log.debug("发短信");
    }
}

结果:

这样就通过事件,来实现解耦     


总结

学到了什么?

1.BeanFactory与ApplicationContext 并不仅仅是简单接口继承的关系,ApplicationContext组合并扩展了BeanFactory的功能(BeanFactory是ApplicationContext的成员方法)

2.ApplicationContext的四个父接口的功能  MessageSource 国际化的能力(翻译)、ResourcePatternResolver 通配符匹配资源(classpath: 和classpath*:等)、EnvironmentCapable 读取环境信息 (可以读取系统环境变量 或者是application.properties的信息)、ApplicationEventPublisher(发布事件对象 --可以用于解耦)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值