学习过程中额外知识点记录

额外知识点记录

  1. spring-boot-cli-2.5.3-bin.zip
    第3章节中,spring-boot-cli 中提供的 spring 脚本,关于获取相关参数,设置环境变量的方式很好,之后学习一下,记录并应用到我的程序中。

  2. start.spring.io 中创建的新项目,会自带一个 mvnw ,看一下。

  3. maven 的 <dependencyManagement> 需要看一下,什么时候需要使用它,即其作用。

  4. maven 查看 依赖 mvn dependency:tree

Executable jars and Java

  1. Executable jars (sometimes called “fat jars”)

    are archives containing your compiled classes along with all of the jar dependencies that your code needs to run.
    是包含你的编译类以及你的代码运行所需的所有jar依赖项的存档。

Java 没有提供加载嵌套 jar 文件(jar 中本身包含的 jar 文件)的标准方法。所以目前一般由两种处理方式

  • uber jar , 普通 java 程序打包处理方式
  • sprint boot 的 executable jars
  1. 许多开发者使用 “uber” jar。uber jar将所有应用程序依赖的所有类打包成一个单一的存档。

    缺点:
    这种方法的问题在于,很难查看应用程序中包含哪些库。如果在多个jar中使用相同的文件名(但内容不同),也会产生问题。

  2. Spring Boot 采用了不同于 “uber” jar 的方式,创建 executable jars。可以实际上直接将 jar 嵌套在一个jar文件中。

Maven 打包

在 Spring Boot 的 测试样例中,打包一个 可执行 jar,需要添加下面的内容,但是由于 spring-boot-starter-parent POM 中包含了 配置已绑定了repackage目标,所以这里不需要了,但是如果没哟依赖 spring-boot-starter-parent 则需要自己添加 配置



org.springframework.boot
spring-boot-maven-plugin


没有依赖 spring-boot-starter-parent 时需要 下面的内容,即添加 这部分内容

org.springframework.boot
spring-boot-maven-plugin
2.1.1.RELEASE



repackage



  1. 我们建议您遵循 Java 建议的包命名约定,并使用反向域名(例如,com.example.project)

    • package
  2. 标准的 ${name} 属性占位符语法

  3. Spring Boot 特性章节中,外化配置
    问题:

  4. lower order property sources , 这里的 lower order 是在哪里定义的?

  5. The list is ordered by precedence (with values from lower items overriding earlier ones). 列表按优先级排序(较低项目的值覆盖较早项目的值)

    • 这里也是,这个 lower items 是怎么定义的? a,b,c 这三个值,a低?还是c低? 这是国外固有的顺序?还是哪里定义的顺序?
    • 从上下文来看,a>b>c,但是还是对官方文档中使用 lower 这个词有疑惑。

问题:
加载的文件被作为 PropertySources 添加到Spring的 Environment 中。

@PropertySource 注解 与 properties 配置文件 和 PropertySource 三者之间的关系?

  1. joda-time 看到好多项目都在用这个 jar ,查一下它的作用和优点。

  2. 目前来说,json 转换 的 jar,推荐使用 jackson 的,更稳定,alibaba 的 fastjson 不能用,bug 太多。

  3. antlr 是个很有意思的工具,美团关于 hiveql 解析成 MapReduce 任务的文章中有提到。spark 等也有使用。

  4. 这意味着诸如 "GET /projects/spring-boot.json" 之类的请求将不会与 @GetMapping("/projects/spring-boot") 映射相匹配。

  • 为什么?不用后缀模式匹配不是反而能匹配到吗?
  1. API中endpoints是什么意思?

  2. Spring 的命名特点,作为源,命名方式为 xxxSource 。
    例如:

  • DataSource
  • PropertySource
  1. 为什么 Tomcat,Jboss等这些称为 服务器?
    硬件层面上,
    软件层面上,

我们用Java开发的Web应用只是一个半成品,类似于一个插件,而服务器则像一个收发器
我们开发的Web 程序,不需要考虑如何接收HTTP请求和响应HTTP请求
软件层面的服务器,帮我们接收和响应 HTTP 请求

  1. spring 中是如何做到集成 tomcat 和我们的 web 代码的?我们写 spring 应用时,入口是有 main方法的,tomcat 自身启动也有main方法,他们怎么处理到一起的?

  2. @Autowired 进行构造函数注入,标记你希望 Spring 使用的哪个构造函数。(没用@Autowired 标注的构造函数怎么用?通过 new 实例的方式?还是有其他方式调用?)

为什么要用?什么时候用?怎么用?实际生产过程中怎么组合使用?

用作 Spring Bean 时自动装配 ? 自动装配是什么意思?自动创建实例?new ?

JPA 中 没有 @Table 的注解,所以 @Entity 实体,就代表着这是一张表,会映射到 同名的表中

demo() 方法返回一个 CommandLineRunner bean,该 bean 在应用程序启动时自动运行代码。

@Configuration可理解为用spring的时候xml里面的标签

@Bean可理解为用spring的时候xml里面的标签


将构造函数、字段、setter 方法或配置方法标记为由 Spring 的依赖注入工具自动装配。

这是 JSR-330 Inject 注释的替代方法,添加了 required-vs-optional 语义。

Autowired Constructors
任何给定的 bean 类只有一个构造函数可以声明这个 annotation,并将 required() 属性设置为 true,指示构造函数在用作 Spring bean 时自动装配。

此外,如果 required 属性设置为 true,则只能使用 @Autowired 注释单个构造函数。

如果多个非必需构造函数声明了注解,它们将被视为自动装配的候选者。

将选择通过匹配 Spring 容器中的 bean 可以满足的依赖项数量最多的构造函数。

如果没有一个候选可以满足,那么将使用主/默认构造函数(如果存在)。

类似地,如果一个类声明了多个构造函数,但没有一个用 @Autowired 注释,则将使用主/默认构造函数(如果存在)。

如果一个类只声明一个构造函数开始,它将始终被使用,即使没有注释。

带注释的构造函数不必是公共的。

Autowired Fields
字段在构建 bean 之后立即注入,在调用任何配置方法之前。
这样的配置字段不必是公开的。

(问题:什么是配置方法config methods?)

Autowired Methods
配置方法可以有任意名称和任意数量的参数;

这些参数中的每一个都将使用 Spring 容器中的匹配 bean 自动装配。

Bean 属性 setter 方法实际上只是这种通用配置方法的一个特例。

这样的配置方法不必是公开的。

Autowired Parameters
尽管从 Spring Framework 5.0 开始,@Autowired 可以在技术上在单个方法或构造函数参数上声明,但框架的大多数部分都忽略了此类声明。

核心 Spring Framework 中唯一主动支持自动装配参数的部分是 spring-test 模块中的 JUnit Jupiter 支持(有关详细信息,请参阅 TestContext 框架参考文档)。

Multiple Arguments and ‘required’ Semantics
在多参数构造函数或方法的情况下, required() 属性适用于所有参数。

单个参数可以声明为 Java-8 样式 Optional,或者从 Spring Framework 5.0 开始,也可以声明为 @Nullable 或 Kotlin 中的非空参数类型,覆盖基本的“必需”语义。

Autowiring Arrays, Collections, and Maps自动装配数组、集合和映射

对于数组、集合或映射依赖类型,容器自动装配与声明的值类型匹配的所有 bean。

为此,必须将映射键(the map keys)声明为 String 类型,该类型将解析为相应的 bean 名称。

这样一个容器提供的集合将被排序,考虑目标组件的 Ordered 和 @Order 值,否则按照它们在容器中的注册顺序。

或者,单个匹配的目标 bean 也可能是一般类型的 Collection 或 Map 本身,因此被注入。

BeanPostProcessor 或 BeanFactoryPostProcessor 不支持
请注意,实际注入是通过 BeanPostProcessor 执行的,这反过来意味着您不能使用 @Autowired 将引用注入 BeanPostProcessor 或 BeanFactoryPostProcessor 类型。

请查阅 AutowiredAnnotationBeanPostProcessor 类的 javadoc(默认情况下,它会检查是否存在此注释)。

  1. 在创建/声明 Bean
  2. 扫描 Bean,对 Bean 进行初始化,配置和依赖管理。
  3. 注入

大体了解了 @Component 与 @Bean 之间的区别,

还有一个问题,为什么要定义 Bean 并注册到 Spring 容器中?

问题,@Autowired 在 字段,set方法,构造函数中标注有什么区别?


关于 Bean 的 @DependsOn , @Lazy , @Scope

2021-08-18 18:39:47.519 INFO 4960 — [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit ‘default’
myBean, Bean开始初始化…
yourBean, Bean开始初始化…
theirBean2, Bean开始初始化…
2021-08-18 18:39:48.607 INFO 4960 — [ main] c.e.accessingdatajpa.BeansApplication : Started BeansApplication in 10.314 seconds (JVM running for 11.611)
myBean, Bean开始初始化…
myBean, MyBean使用…
theirBean, MyBean使用…

2021-08-18 18:44:02.168 INFO 16008 — [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit ‘default’
myBean, Bean开始初始化…
yourBean, Bean开始初始化…
theirBean2, Bean开始初始化…
theirBean, Bean开始初始化…
2021-08-18 18:44:03.176 INFO 16008 — [ main] c.e.accessingdatajpa.BeansApplication : Started BeansApplication in 8.581 seconds (JVM running for 10.016)
myBean, Bean开始初始化…
myBean, MyBean使用…
theirBean, MyBean使用…

2021-08-18 18:47:49.593 INFO 9840 — [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit ‘default’
myBean, Bean开始初始化…
yourBean, Bean开始初始化…
theirBean2, Bean开始初始化…
theirBean, Bean开始初始化…
2021-08-18 18:47:50.817 INFO 9840 — [ main] c.e.accessingdatajpa.BeansApplication : Started BeansApplication in 10.624 seconds (JVM running for 12.203)
theirBean, MyBean使用…

Object的hashCode()默认是返回内存地址的,但是hashCode()可以重写,所以hashCode()不能代表内存地址的不同

System.identityHashCode(Object)方法可以返回对象的内存地址,不管该对象的类是否重写了hashCode()方法。

问题,当什么情况会在多个 @Configuration 配置多个组件扫描?

对于是否需要写接口:

对于是否需要写接口:

写接口的理由:

  1. 使用接口更多的是一种规范吧,好的代码是让初学者都明白代码逻辑。
  2. GCLIB代理不需要接口,但是JDK动态代理, 需要接口。
  3. 有了接口层可以快速知道有哪些方法,而直接写impl的话,肯定会有一些杂七杂八的方法啥的影响阅读体验。代码永远是用来阅读的,不方便阅读,会不方便维护。
  4. 写interface可以比较快的找到可以用的方法。上面可以注释。不用在impl里翻找需要的逻辑。(与理由3类似)
  5. 使用接口的另一个原因,提高代码可测性,这也是为什么后面spring推荐构造器注入的原因。 当service调用远程网络,依赖不同环境时。我们可以使用mock实现替换当前service实现,实现对环境依赖的解耦,返回mock数据。
  6. 小项目没有多实现,可以不写,但是当需求增加后,service 层需要多种不同的实现后,就感受到面向接口开发的好处了。

不写接口的理由:

  1. 小项目,没有多实现的情况下,多写一个接口,增加工作量,麻烦。

@Scope 注解源码注释中有一段内容可以使用:

as a type-level annotation, instances of the annotated type。

as a method-level annotation, the instance returned from the method.

annotation 注解 源码中,对注解可作用的类型的表述,Type表示如下:

1
2
/** Class, interface (including annotation type), or enum declaration */ 
TYPE,

根据类型获取 Bean 的局限和扩展方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	// SpringApplication 根据类型获取 Bean
ConfigurableApplicationContext context = SpringApplication.run(AccessDemo.class, args);
CommandLineRunner commandLineRunner = context.getBean(CommandLineRunner.class);
System.out.println(commandLineRunner.toString());

// 当前 context 中有两个 CommandLineRunner 接口实现的 Bean,所以遇到如下报错,

// 报错
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.CommandLineRunner' available: expected single matching bean but found 2: CLRunner,demoBefore
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1262)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
at com.spoonli.demo.AccessDemo.main(AccessDemo.java:52)

从上面报错可以知道,当使用默认的 getBean() 方法获取 Bean 时,采用根据类型获取,只能在当前类型的 Bean 在 Spring Context 中只存在一个的情况下才行,如果同一类型同时存在多个不同名称的 Bean 时,则会报错

操作方法:

  1. 改用名称来获取;
  2. 如果是使用 @Autowired来自动装配时,与 @Qualify 注解一起使用,获取指定类型指定名称的 Bean;
  3. context.getBeansOfType(CommandLineRunner.class).values() 使用这个方法来获取指定类型所有的 Bean ,然后循环处理。

maven 项目已 project 导入 和 已module形式导入有什么不同?

确认一下 Spring Boot 外部配置文件的通配符含义

Runnable 的 poll 和 take 有什么区别?

通过创建 Thread 去执行 Runnable 的task ?所有的 task 都是 Runnable 的,那么怎么体现 线程池中的线程运行的 task ?不是 task.run() 自己执行的run() 吗?

  • 是通过一次运行固定资源个task 执行来达到所谓的控制线程数的效果的吗?

没有理解什么是线程? 当 new Thread 的时候,是在做什么?

mybatis-generator-core-.pom.lastUpdated
这个文件很可能导致了本地无法直接解决依赖问题,先删掉看看

POST _analyze
{
“text”: “美国留给伊拉克的是一个烂摊子吗?”,
“analyzer”: “ik_max_word”
}

Docker 中水平伸缩只能用于无状态计算服务,具有数据状态的都不适合直接放在 Docker 里面,如果 Docker 中安装数据库,存储服务需要单独提供。

Docker 推荐服务挂掉,自动启动新容器,而不是继续重启容器服务。

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2022-2023 ligongzhao
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信