深入学习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 不会做的事
- 不会主动调用BeanFactory 后处理器
- 不会主动添加Bean后处理器
- 不会主动初始化单例
- 不会解析beanFactory 还不会解析¥{ } 和#{ }
- 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 的创建方法 作用
750

被折叠的 条评论
为什么被折叠?



