第一讲:容器接口
目录
一、BeanFactory与ApplicationContext
1.BeanFactory与ApplicationContext以及ConfigurableApplicationContext接口的关系
2.ApplicationContext其实调用的还是BeanFactory来进行解决
3.BeanFactory 是ApplicationContext的成员变量
2.BeanFactory其中的实现类---管理单例对象的类DefalutSingletionBeanFatorty
学习目标
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(发布事件对象 --可以用于解耦)