对SpringBoot后续的再补充学习:

使用IDEA创建项目不勾选任何组件

默认的POM结构:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.dai</groupId>
<artifactId>spirngboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spirngboot</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies> <!-- 运行核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency> <dependency>
<!-- 测试环境支持 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> <build>
<!-- 项目打包插件 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

所谓的组件也就是一个个的组件坐标,我们可以自行配置。

这里的一些常用组件可以在IDEA初始化项目之后放POM里面:

 <!-- 实体类简化辅助 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency> <!-- MVC支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!-- 热部署与开发帮助支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency> <!-- 配置文件依赖提示支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

BeanDefinition对象

在之前的Spring理解是:

一个类ClassA.java注解了SpringBean,或者使用了Spring的XML配置,通过注解和XML配置的信息

我们就可以得到一个Bean对象,这个Bean对象由Spring管理和创建

但是现在不一样,这个实例是由BeanDefinition创建而来:

Bean定义对象存储了Bean对象的描述信息

OriginClass.java
|
BeanDefinition.java
|
BeanOriginClass.java

所在位置:

是一个接口,其实现类众多

org.springframework.beans.factory.config.BeanDefinition

属性:

String getParentName(); 父类名称
String getBeanClassName(); Bean的类名称
getScope(); 获取对象模式,单利还是原型
isLazyInit(); 是否懒加载
...

如何证明BeanDefinition创建

首先是一个类A,标注了Spring组件:

@Component
public class ClassA {
public ClassA() {
System.out.println("A实例被创建");
}
}

其次一个类B组合了类A也标注了组件

但是类A属性不自动装配:

@Component
public class ClassB { private ClassA classA; public ClassB() {
System.out.println("B实例被创建");
} public ClassA getClassA() {
return classA;
} public void setClassA(ClassA classA) {
this.classA = classA;
}
}

注册配置:

@Configurationpublic class TestConfiguration {

    @Bean
public ClassB classB() {
return new ClassB();
} @Bean
public ClassA classA() {
return new ClassA();
}
}

我们运行测试类很正常的发现在类B中的类A得到的是空

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
public class DefinitionTest { @Autowired
private ClassB classB; @Test
public void testSample() {
System.out.println(classB.getClassA());
}
}

结果:

B实例被创建
A实例被创建
null Process finished with exit code 0

我们可以通过定义对象去改变:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
// GenericBeanDefinition classAGenericBeanDefinition = (GenericBeanDefinition)configurableListableBeanFactory.getBeanDefinition("classB");
// classAGenericBeanDefinition.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME); RootBeanDefinition classARootBeanDefinition = (RootBeanDefinition)configurableListableBeanFactory.getBeanDefinition("classB");
classARootBeanDefinition.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
}
}

配置类加载:

@Configuration
@Import(MyBeanFactoryPostProcessor.class)
public class TestConfiguration { @Bean
public ClassB classB() {
return new ClassB();
} @Bean
public ClassA classA() {
return new ClassA();
}
}

测试结果类A实例能够获取:

B实例被创建
A实例被创建。。。
cn.dzz.bean.ClassA@587e5365 Process finished with exit code 0

但是注意类B需要提供对应的GETTER & SETTER

在上面的定义修改中,Generic的实现类并不能被运行:

Caused by: 
  java.lang.ClassCastException:
    org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition
    cannot be cast to org.springframework.beans.factory.support.GenericBeanDefinition

并不能强转为这个$ConfigurationClassBeanDefinition

所以需要查看下面有哪些子实现类

查看方式是点击这里:

Bean构造器参数值注入 ConstructorArgumentValues

这里有一个配置的问题,我们的类注册只能这样注解才能让定义处理器生效

就是让Spring以包扫描的方式进行

@Configuration
@ComponentScan("cn.dzz")
public class TestConfiguration {
}

不能以Import方式和@Bean配置类写方法的方式进行导入

类C的构造器声明:

@Component
public class ClassC { public ClassC() {
System.out.println("无参数");
} public ClassC(int i) {
System.out.println("一个整数参数");
} public ClassC(String i,int ii) {
System.out.println("一个字符参数,一个整数参数");
} }

构造器方法注入定义修改

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
GenericBeanDefinition classAGenericBeanDefinition = (GenericBeanDefinition)configurableListableBeanFactory.getBeanDefinition("classB");
classAGenericBeanDefinition.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE); // RootBeanDefinition classARootBeanDefinition = (RootBeanDefinition)configurableListableBeanFactory.getBeanDefinition("classB");
// classARootBeanDefinition.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME); // RootBeanDefinition classCRootBeanDefinition = (RootBeanDefinition)configurableListableBeanFactory.getBeanDefinition("classC");
// ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
// constructorArgumentValues.addIndexedArgumentValue(0,"哈哈哈");
// constructorArgumentValues.addIndexedArgumentValue(1,233);
// classCRootBeanDefinition.setConstructorArgumentValues(constructorArgumentValues); GenericBeanDefinition classCGenericBeanDefinition = (GenericBeanDefinition)configurableListableBeanFactory.getBeanDefinition("classC");
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0,"哈哈哈");
constructorArgumentValues.addIndexedArgumentValue(1,233);
classCGenericBeanDefinition.setConstructorArgumentValues(constructorArgumentValues);
}
}

测试结果:

A实例被创建
B实例被创建
一个字符参数,一个整数参数
cn.dzz.bean.ClassA@2638011 Process finished with exit code 0

Scope定义的修改

首先默认取两个对象测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
public class DefinitionTest { @Autowired
private ClassB classB; @Autowired
private ClassC classC01;
@Autowired
private ClassC classC02; @Test
public void testSample() {
System.out.println(classB.getClassA()); System.out.println(classC01 == classC02);
}
}

结果为True,因为我们知道Spring默认了Bean的Scope为单例Singleton

A实例被创建
B实例被创建
一个字符参数,一个整数参数
一个字符参数,一个整数参数
cn.dzz.bean.ClassA@117e949d
true Process finished with exit code 0

但是在上面的自定义的定义处理器更改Scope为原型模式之后则为False了

classCGenericBeanDefinition.setScope("prototype");

结果:

A实例被创建
B实例被创建
一个字符参数,一个整数参数
一个字符参数,一个整数参数
cn.dzz.bean.ClassA@117e949d
false Process finished with exit code 0

【SpringBoot】Re 01 补充学习的更多相关文章

  1. ArcGIS API for JavaScript 4.2学习笔记[31] (补充学习)Task类

    Task这个东西很有用,是AJS中用于解决各种乱七八糟任务的一个类.它有很多子类,有用于空间分析的,有用于空间查询的,等等. 这篇作为补充学习的第一篇,也是进阶学习的第一篇,我就改个写法. 我将使用思 ...

  2. 20145219 《Java程序设计》第01周学习总结

    20145219 <Java程序设计>第01周学习总结 教材学习内容总结 软件分类:系统软件(DOS.Windows.Linux等).应用软件(扫雷.QQ等) 人机交互方式:图形化界面.命 ...

  3. 【原创】SpringBoot & SpringCloud 快速入门学习笔记(完整示例)

    [原创]SpringBoot & SpringCloud 快速入门学习笔记(完整示例) 1月前在系统的学习SpringBoot和SpringCloud,同时整理了快速入门示例,方便能针对每个知 ...

  4. SpringBoot中JPA的学习

    SpringBoot中JPA的学习 准备环境和项目配置 写一下学习JPA的过程,主要是结合之前SpringBoot + Vue的项目和网上的博客学习一下. 首先,需要配置一下maven文件,有这么两个 ...

  5. 快速体验Spring Boot了解使用、运行和打包 | SpringBoot 2.7.2学习系列

    SpringBoot 2.7.2 学习系列,本节内容快速体验Spring Boot,带大家了解它的基本使用.运行和打包. Spring Boot 基于 Spring 框架,底层离不开 IoC.AoP ...

  6. springboot 尚桂谷学习总结01

    ------springboot 技术入门------ 1.springboot 简介: 优点: 简化spring 应用开发的一个框架 整个spring技术栈的一个大整合 ------微服务----- ...

  7. Springboot简介01

    前言: spring是近几年java中最具有代表而且最为流行的框架,spring是基于aop和IOC的思想,在我们的项目中充当了一个粘合剂的作用,既可以成为对象工厂,来管理我们的controller. ...

  8. JDK1.8源码分析01之学习建议(可以延伸其他源码学习)

    序言:目前有个计划就是准备看一下源码,来提升自己的技术实力.同时现在好多面试官都喜欢问源码,问你是否读过JDK源码等等? 针对如何阅读源码,也请教了我的老师.下面就先来看看老师的回答,也许会有帮助呢. ...

  9. SpringBoot官方文档学习(三)配置文件、日志、国际化和JSON

    一.Profiles Spring配置文件提供了一种方法来隔离应用程序配置的各个部分,并使其仅在某些环境中可用.任何@Component.@Configuration或@ConfigurationPr ...

  10. SpringBoot官方文档学习(一)SpringApplication

    Springboot通过main方法启动,在许多情况下,委派给静态SpringApplication.run方法: public static void main(String[] args) { S ...

随机推荐

  1. idea mapper xml 文件报红

    在使用 idea 打开 mapper 文件,出现一下报红错误: 可以看到数据表和字段都是红色的. 解决方案 打开设置,window版本是打开Settings: 找到 Languages & F ...

  2. bpmnjs

    在 bpmn.js 中,`bpmnModeler.get()` 方法用于获取不同的模块,你可以通过这些模块来访问和操作 BPMN 模型的不同部分.以下是一些常用的模块和对应的用途: 1. **Canv ...

  3. 使用Vulkan-Loader将ncnn代码改成Dynamic Loader Vulkan的形式

    原本你写的程序是静态链接的系统的vulkan-1.dll,如果系统不存在vulkan-1.dll,则会直接崩溃. 关于将ncnn静态链接vulkan改成动态加载vulkan的形式,然后提供这两个函数 ...

  4. NCNN的内存显存分配器ncnn::Allocator & ncnn::VkAllocator翻译及其差异对比的学习笔记(nihui亲审过滴)

    NCNN的内存分配器 ncnn::Allocator 通用内存分配器   ncnn::PoolAllocator 内存池分配器 可以设置池大小,减少分配内存和析构内存次数,空间换时间   ncnn:: ...

  5. 对于 EI K 逆序对排列计数的另一种自然求和方法的理解

    有一个简单的 \(O(n^3)\) DP,考虑 \(f_{x + 1, k} = \sum_{j = 0}^{x} f_{x, k - j}\),利用前缀和优化即可. 考虑这实际上是 \(f_{x + ...

  6. tomcat部署Jenkins

    安装环境 jdk 1.8 tomcat 9.0 jenkins 2.290 准备工作 安装好Tomcat,8080端口启动 安装好jdk,配置好环境变量 ECS服务器安全组放开8080端口 关闭防火墙 ...

  7. leetcode_2-两数相加_javascript

    题目 2.两数相加 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新 ...

  8. MyBatis 关于查询语句上配置的详细内容

    1. MyBatis 关于查询语句上配置的详细内容 @ 目录 1. MyBatis 关于查询语句上配置的详细内容 2. 准备工作 3. SQL查询结果,返回为POJO实体类型 4. SQL查询结果,返 ...

  9. LocalDateTime日期格式化和指定日期的时分秒

    LocalDateTime日期格式化和指定日期的时分秒 package com.example.core.mydemo.date; import java.time.LocalDate; import ...

  10. 关于 "= default" 和 "= delete" 函数

    在 C++ 11 中,"= default" 和 "= delete" 函数使我们能够显示指定成员函数是否自动生成. 其中,"= delete&quo ...