SpringBoot高级原理

news2024/10/7 8:20:36

SpringBoot高级原理

今日内容:

  • 理解SpringBoot自动化配置源码
  • 理解SpringBoot健康监控

1 SpringBoot自动化配置原理

01-SpringBoot2高级-starter依赖管理机制

目的:通过依赖能了解SpringBoot管理了哪些starter

讲解:

  1. 通过依赖 spring-boot-dependencies 搜索 starter- 发现非常多的官方starter,并且已经帮助我们管理好了版本。

  2. 项目中使用直接引入对应的 starter 即可,这个场景下需要的依赖就会自动导入到项目中,简化了繁琐的依赖。

    如果需要修改版本可以有两种方式:

    • 重写maven属性
    • 使用Maven依赖管理的就近原则
  3. 引入 starter 不仅仅是帮助我们管理了依赖,还帮我做了很多的默认的配置信息,简化了大量的配置,使用更加的简单。

  4. 所有的场景启动器的底层都依赖 spring-boot-starter

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.3.10.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    

小结:

  • 引入官方starter依赖默认都可以不写版本
  • 如果配置满足您当前开发需要,则默认配置即可
02-SpringBoot2高级-自动化配置初体验

目的:以web MVC自动化配置原理为例讲解,能够理解web MVC自动化配置加入了哪些依赖,做了哪些默认配置。

讲解:

回忆一下:SpringMVC学习时候,我们在 SSM整合时;

添加spring及spring web mvc相关依赖

springmvc配置类:

​ 1、扫描controller层

​ 2、静态资源控制

​ 3、…

servlet容器配置类:

​ 1、扫描springmvc配置类

​ 2、扫描spring配置类

​ 3、设置哪些请求交给springmvc处理

​ 4、POST请求乱码过滤器

部署还需要单独的tomcat

也就是说:我们现在需要在开发业务代码前,就必须要准备好这些环境,否则无法完成业务代码,这就是我们现在的问题。

让这些问题成为过去,现在我们就探索一下SpringBoot是如何帮助我们完成强大而又简单自动化配置的。

引入 web 开发场景启动器依赖:

<!--web开发的起步依赖   场景启动器依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

帮助我们做了以下自动化配置:

  1. 依赖版本和依赖什么jar都不需要开发者关注

  2. 自动化配置

    • 自动配好SpringMVC
      • 引入SpringMVC全套组件
      • 自动配好SpringMVC常用组件(三大组件,文件上传等)
    • 自动配好Web常见功能,如:字符编码问题,静态资源管理
  3. 自动配好Tomcat

小结:

  • 有了SpringBoot以后,让开发人员重点关注业务本身,而不是环境上,提升了开发效率。
03-SpringBoot2高级-底层原理-@Configuration配置注解

目的:掌握@Configuration注解的作用及新特性

讲解:

1、@Configuration注解的作用是替代原始 spring配置文件 功能

演示:

1)编写配置类

package com.itheima.sh.config;

import com.itheima.sh.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 1、@Configuration 替代 spring配置文件(配置bean)
 * 2、组件源码中包含 @Component 注解,当前类也会注册到 IOC 容器,默认类名小写
 * 3、默认都是单例的
 */
@Configuration
public class MyConfig {
    
    @Bean   // 默认方法名称作为容器中的name
    public User getUser() {
        return new User();
    }
}

2)在引导类编写代码测试:

@SpringBootApplication
@MapperScan(basePackages = "com.itheima.sh.mapper")
public class DataApplication {
  public static void main(String[] args) {
    ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);

   // 根据name获取容器中的bean
    User user1 = applicationContext.getBean("getUser", User.class);
    User user2 = applicationContext.getBean("getUser", User.class);
    System.out.println(user1 == user2);
    
    MyConfig myConfig1 = applicationContext.getBean("myConfig", MyConfig.class);
    MyConfig myConfig2 = applicationContext.getBean("myConfig", MyConfig.class);
    System.out.println(myConfig1 == myConfig2);
    // 注意:如果 MYConfig配置类没有按照规范编写,则容器中bean 的name为 类名
  }
}

SpringBoot 提供一个注解和当前注解功能一样:@SpringBootConfiguration

2、proxyBeanMethods:代理bean的方法属性(since spring 5.2以后)

在这里插入图片描述

功能:

  • proxyBeanMethods = true:Full模式,保证每个@Bean方法被调用多少次返回的组件都是单实例的

  • proxyBeanMethods = false:Lite模式,每个@Bean方法被调用多少次返回的组件都是新创建的

演示:

  1. 默认 proxyBeanMethods=true,springBoot会检查这个组件是否在容器中有,有则直接引用
// 默认 proxyBeanMethods=true springBoot会检查这个组件是否在容器中有,有则直接引用
User user3 = myConfig1.getUser();
System.out.println(user1 == user3);  // true
  1. 修改 proxyBeanMethods=false,则每调用一次Spring就会创建一个新的Bean对象

在这里插入图片描述

在执行结果则为 false, 证明两次获取的bean不是同一个bean。

小结:

  • 组件依赖必须使用Full模式默认。

  • Full模式每次都会检查bean,效率较Lite模式慢

04-SpringBoot2高级-底层原理-@Import注解使用1

目的:能够理解@Import注解作用及4种使用方式

讲解:

作用:使用@Import导入的类会被Spring加载到IOC容器中

@Import提供4种用法:

  1. 导入Bean
  2. 导入配置类
  3. 导入 ImportSelector 实现类。一般用于加载配置文件中的类
  4. 导入 ImportBeanDefinitionRegistrar 实现类

实现:

1、导入Bean

package com.itheima.sh;

import com.itheima.sh.pojo.User;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;

import java.util.Map;

@SpringBootApplication
@Import(User.class)  
//会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径

public class DataApplication {
  public static void main(String[] args) {
    ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);

    Map<String, User> map = applicationContext.getBeansOfType(User.class);
    System.out.println(map);
    
    User user1 = applicationContext.getBean("com.itheima.sh.pojo.User", User.class);
    System.out.println(user1);

  }
}

2、导入配置类

package com.itheima.sh;

import com.itheima.sh.config.MyConfig;
import com.itheima.sh.pojo.User;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;

import java.util.Map;

@SpringBootApplication
@MapperScan(basePackages = "com.itheima.sh.mapper")
//@Import(User.class)
//1、会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径

@Import(MyConfig.class)
//2、创建MyConfig bean,并且类中有 带有@Bean注解方法,创建对象存到IOC容器,bean名称为:默认方法名称
public class DataApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);

        //{getUser=com.itheima.sh.pojo.User@1b4a3a1}
        Map<String, User> map = applicationContext.getBeansOfType(User.class);
        System.out.println(map);

        User user1 = applicationContext.getBean("getUser", User.class);
        System.out.println(user1);

        Map<String, MyConfig> config = applicationContext.getBeansOfType(MyConfig.class);
        //{com.itheima.sh.config.MyConfig=com.itheima.sh.config.MyConfig@7e848aea}
        System.out.println(config);
    }
}
05-SpringBoot2高级-底层原理-@Import注解使用2

目的:讲解@Import注解使用另外两种使用方式

步骤:

  1. 导入 ImportSelector 实现类。一般用于加载配置文件中的类
  2. 导入 ImportBeanDefinitionRegistrar 实现类

实现:

导入 ImportSelector 实现类。一般用于加载配置文件中的类

1、编写 ImportSelector 实现类,MyImportSelector

2、引导类导入

package com.itheima.sh;

import com.itheima.sh.config.MyImportSelector;
import com.itheima.sh.pojo.User;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;

import java.util.Map;

@SpringBootApplication
@MapperScan(basePackages = "com.itheima.sh.mapper")
//@Import(User.class)
//1、会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径

//@Import(MyConfig.class)
//2、创建MyConfig bean,并且类中有 带有@Bean注解方法,创建对象存到IOC容器,bean名称为:默认方法名称

@Import(MyImportSelector.class)
//3、创建MyConfig bean 名称为:类名全路径,创建带有@Bean注解方法实例,名称为:方法名称
public class DataApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);

      Map<String, MyConfig> map = applicationContext.getBeansOfType(MyConfig.class);
      //{com.itheima.sh.config.MyConfig=com.itheima.sh.config.MyConfig@44384b4a}
      System.out.println(map);

      Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
      //{getUser=com.itheima.sh.pojo.User@5cc3e49b}
      System.out.println(userMap);

    }
}

导入 ImportBeanDefinitionRegistrar 实现类

1、编写 ImportBeanDefinitionRegistrar 实现类,MyImportBeanDefinitionRegistrar

package com.itheima.sh.config;

import com.itheima.sh.pojo.User;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

  /**
     * @param importingClassMetadata 导入类的元注解信息
     * @param registry Bean注册表
     */
  @Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
      .rootBeanDefinition(User.class).getBeanDefinition();
    registry.registerBeanDefinition("user", beanDefinition);
  }
}

2、引导类测试

package com.itheima.sh;

import com.itheima.sh.config.MyImportBeanDefinitionRegistrar;
import com.itheima.sh.pojo.User;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;

import java.util.Map;

@SpringBootApplication
@MapperScan(basePackages = "com.itheima.sh.mapper")

//@Import(User.class)
//1、会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径

//@Import(MyConfig.class)
//2、创建MyConfig bean,并且类中有 带有@Bean注解方法,创建对象存到IOC容器,bean名称为:默认方法名称

//@Import(MyImportSelector.class)
//3、创建MyConfig bean 名称为:类名全路径,创建带有@Bean注解方法实例,名称为:方法名称

@Import(MyImportBeanDefinitionRegistrar.class)
//4、创建Bean,名称:在registerBeanDefinition中定义
public class DataApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);

        Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
        //{user=com.itheima.sh.pojo.User@23c7cb18}
        System.out.println(userMap);

    }
}

小结:

  • 讲解当前小节的目的主要是为源码准备
  • 还有我们也可以知道创建Bean对象,还可以使用@Import四种方式
06-SpringBoot2高级-底层原理-@Conditional衍生条件装配

目的:理解@Conditional衍生条件装配的作用

讲解:

作用:条件装配,满足Conditional指定的条件,则进行组件注入,初始化Bean对象到IOC容器

image-20210503232237027

演示:

在RedisConfig类中添加注释:

方法中定义:

在这里插入图片描述

类上定义:

在这里插入图片描述

注意:也可以添加到 类上, 满足条件则类及类中的对象生效。

小结:

  • @ConditionalOnXXX 注解存在的意义是:满足条件当前类或者Bean才有效,按需导入。
07-SpringBoot2高级-底层原理-@ConfigurationProperties配置绑定

目的:

回顾 @ConfigurationProperties配置绑定 存在的目的是:获取配置属性或者是配置文件指定前缀的属性信息,并且初始化Bean对象到 IOC 容器。

由此我们可以想:将来的配置我们可以放在配置文件中,通过这个注解来读取并封装成对象

在这里插入图片描述

08-SpringBoot2高级-自动化配置原理-@SpringBootApplication入口分析

目的:能够理解SpringBoot自动化配置流程中@SpringBootApplication是一个组合注解,及每一个注解的作用能够知道作用。

讲解:

1、SpringBoot是一个组合注解

在这里插入图片描述

2、@SpringBootConfiguration注解作用

  • @SpringBootConfiguration是对@Configuration注解的包装,proxyBeanMethods 默认配置 true, full模式(单例Bean)

  • 标识是一个配置类,所以 引导类也是配置类

3、@ComponentScan注解作用

  • 组件扫描,默认扫描的规则 引导类所在的包及其子包所有带注解的类

问题:

  1. 在引导类中配置 @Bean 注解可以吗?
  2. 为什么Controller、service类添加完注解后,不需要添加扫描包?
09-SpringBoot2高级-自动化配置原理-@EnableAutoConfiguration自动配置注解

目的:理解@EnableAutoConfiguration自动化配置核心实现注解

讲解:

1、@EnableAutoConfiguration是一个组合注解

在这里插入图片描述

2、@AutoConfigurationPackage注解作用

作用:利用Registrar给容器中导入一系列组件

在这里插入图片描述

点击 Registrar 进入到源码的 register 方法,添加 断点,测试

在这里插入图片描述

通过 debug 程序发现,默认情况下 将引导类的所有包及其子包的组件导入进来

3、@Import(AutoConfigurationImportSelector.class)注解作用

作用:是利用selectImports方法中的 getAutoConfigurationEntry 方法给容器中批量导入相关组件

调用流程分析:

  1. 调用AutoConfigurationImportSelector类中的selectImports方法

  2. 调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类

  3. 利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader)得到所有的组件

  4. 从META-INF/spring.factories位置来加载一个文件。

    默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件

    在这里插入图片描述

    spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories

    在这里插入图片描述

通过这个配置文件加载的自动配置:当前版本(2.3.10)是有127个默认的自动化配置

在这里插入图片描述

小结:

  • 自动化配置默认加载的配置文件在哪?
10-SpringBoot2高级-自动化配置原理-按条件开启自动配置类和配置项

目的:

  • 能够理解所有的自动化配置虽然会全部加载,底层有大量的@ConditionalOnXXX,有很多自动配置类并不能完全开启。
  • 如果配置生效了,则会加载默认的属性配置类,实现默认的对应场景的自动化配置

讲解:

1、以上通过 META-INF/spring.factories 配置文件找到所有的自动化配置类,但 是不是全部的生效的呢?很显然是不可能全部都生效的。

2、以 JdbcTemplateAutoConfiguration 为例讲解, 进入到 JdbcTemplateAutoConfiguration 自动化配置类。

//配置类,Lite模式
@Configuration(proxyBeanMethods = false)
//存在 DataSource、JdbcTemplate 类时再加载当前类
@ConditionalOnClass({DataSource.class, JdbcTemplate.class })

//容器中只有一个指定的Bean,或者这个Bean是首选Bean 加载当前类
@ConditionalOnSingleCandidate(DataSource.class)

//在配置类 DataSourceAutoConfiguration 之后执行
@AutoConfigureAfter(DataSourceAutoConfiguration.class)

//如果条件满足:开始加载自动化配置的属性值 JdbcProperties
@EnableConfigurationProperties(JdbcProperties.class)

@Import({JdbcTemplateConfiguration.class, NamedParameterJdbcTemplateConfiguration.class })
public class JdbcTemplateAutoConfiguration {

}

3、JdbcProperties,用于加载默认的配置,如果配置文件配置了该属性,则配置文件就生效。

在这里插入图片描述

4、通过@Import导入JdbcTemplateConfiguration

//配置类,Lite模式
@Configuration(proxyBeanMethods = false)
//没有JdbcOperations类型的bean时加载当前类,而 JdbcTemplate 是 JdbcOperations 接口实现类
@ConditionalOnMissingBean(JdbcOperations.class)
class JdbcTemplateConfiguration {

    @Bean
    @Primary
    JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        JdbcProperties.Template template = properties.getTemplate();
        jdbcTemplate.setFetchSize(template.getFetchSize());
        jdbcTemplate.setMaxRows(template.getMaxRows());
        if (template.getQueryTimeout() != null) {
            jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
        }
        return jdbcTemplate;
    }

}

验证:我们可以在我们自己的项目里面创建一个 JdbcTemplate Bean,看容器创建的Bean执行的是哪一个方法。

@Configuration
public class MyConfig {

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        System.out.println("自定义 JdbcTemplate");
        return jdbcTemplate;
    }
}

结果:保证容器中只有一个 Bean 实例

在这里插入图片描述

问题:

  • 这些不用的 starter 的依赖,能不能导入到我们工程里面? 为什么?
11-SpringBoot2高级-自动化配置原理-debug全流程

目的:能够理解整个SpringBoot启动的完成自动化配置及属性加载的全过程

12-SpringBoot2高级-自动化配置原理-总结

SpringBoot自动化配置流程总结:

  • 程序启动找到自动化配置包下 META-INF/spring.factoriesEnableAutoConfiguration
  • SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
  • 每个自动配置类按照条件进行生效。
  • 生效的配置类就会给容器中装配很多组件
  • 只要容器中有这些组件,相当于这些功能就有了
  • 定制化配置
    • 用户直接自己@Bean替换底层的组件
    • 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxAutoConfiguration
Bean组件
xxxxProperties里面取值
application.properties

开发人员使用步骤总结:

  • 引入场景依赖

  • 查看自动配置了哪些(选做)

    • 自己分析,引入场景对应的自动配置一般都生效了
    • 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
  • 自己分析是否需要修改

  • 参照文档修改配置项,xxxxProperties绑定了配置文件的哪些。

    • 自定义加入或者替换组件,@Bean、@Component等

2 SpringBoot健康监控

13-SpringBoot2高级-监控-健康监控服务

目的:能够理解健康监控actuator的作用

讲解:

每一个微服务在云上部署以后,我们都需要对其进行监控、追踪、审计、控制等。SpringBoot就抽取了Actuator场景,使得我们每个微服务快速引用即可获得生产级别的应用监控、审计等功能。

实现:

1、引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2、启动项目,访问 http://localhost:80/actuator

image-20210504152047942

3、暴露所有监控信息为HTTP

management:
  endpoints:
    enabled-by-default: true #暴露所有端点信息
    web:
      exposure:
        include: '*'  #以web方式暴露

  endpoint:
    health:
      enabled: true   # 开启健康检查详细信息
      show-details: always

访问 http://localhost:80/actuator 会发现内容多了,里面的地址分别都可以访问,记录的是对应的健康监测的信息。

14-SpringBoot2高级-监控-Admin可视化

目的:能够搭建 可视化监控平台

讲解:

SpringBoot Admin 有两个角色,客户端(Client)和服务端(Server)。

Spring Boot Admin为注册的应用程序提供以下功能:

  • 显示健康状况
  • 显示详细信息,例如
    • JVM和内存指标
    • micrometer.io指标
    • 数据源指标
    • 缓存指标
  • 显示内部信息
  • 关注并下载日志文件
  • 查看JVM系统和环境属性
  • 查看Spring Boot配置属性
  • 支持Spring Cloud的可发布/ env-和// refresh-endpoint
  • 轻松的日志级别管理
  • 与JMX-beans交互
  • 查看线程转储
  • 查看http-traces
  • 查看审核事件
  • 查看http端点
  • 查看预定的任务
  • 查看和删除活动会话(使用spring-session)
  • 查看Flyway / Liquibase数据库迁移
  • 下载heapdump
  • 状态更改通知(通过电子邮件,Slack,Hipchat等)
  • 状态更改的事件日志(非持久性)

快速入门:https://codecentric.github.io/spring-boot-admin/2.3.1/#getting-started

实现:

以下为创建服务端和客户端工程步骤:

搭建Server端:

1、创建 admin_server 模块,引入依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.10.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-server</artifactId>
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

</dependencies>

2、开启注解支持

package com.itheima.sh;

import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableAdminServer
public class AdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminApplication.class, args);
    }
}

注意端口修改为:9999

搭建Client端:

1、在任意服务里面引入依赖

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.3.1</version>
</dependency>

2、配置文件

  # 执行admin.server地址
spring:   
  boot:
    admin:
      client:
        url: http://localhost:9999  # admin 服务地址
        instance:
          prefer-ip: true   # 显示IP
  application:
    name: boot_data  # 项目名称
    
management:
  endpoints:
    enabled-by-default: true #暴露所有端点信息
    web:
      exposure:
        include: '*'  #以web方式暴露

  endpoint:
    health:
      enabled: true   # 开启健康检查详细信息
      show-details: always

3、启动服务,访问admin Server http://localhost:9999/

在这里插入图片描述

3 扩展lombok

1、pom依赖:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

2、实体类

@Data  // set/get/tostring ....
@AllArgsConstructor  // 全参
@NoArgsConstructor // 无参构造
@ToString // tostring
@Accessors(chain = true)  // 链式调用
@Builder  // 构建者模式创建对象
@Slf4j  // 日志注解支持
public class User {

    private Long id;
    private String userName;
    private Integer sex;
    private LocalDate birthday;
    private Date created;
    private Date modified;

}

3、测试

//        User user = new User();
        //user = user.setId(1L).setSex(1);
        User user1 = User
                .builder()

                .id(1L)
                .sex(1)
                .created(new Date())

                .build();
        System.out.println("user1: "+user1);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1411840.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

外汇天眼:新坦利斯曼黄金矿业的前首席执行官承认违反新西兰金融市场法

新西兰金融市场管理局&#xff08;FMA&#xff09;今天确认&#xff0c;新西兰证券交易所上市公司新坦利斯曼黄金矿业有限公司的前首席执行官Matthew Geoffrey Hill承认违反了2013年《金融市场行为法》&#xff08;FMCA&#xff09;&#xff0c;在此法案下作出了虚假和误导性陈…

Linux本地部署SVN服务结合内网穿透实现远程访问

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

【wink】如何导出Live实况?

1.首页点击「转Live实况」&#xff0c;即可将图片或视频快速转为Live实况格式。 2.编辑后的视频&#xff0c;可在保存分享页点击「存为Live实况」。&#xff08;本功能仅限iOS用户使用&#xff09;

【每日一题】4.LeetCode——杨辉三角

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢迎各位大佬指点&…

佩戴口罩监测识别摄像机

佩戴口罩监测识别摄像机是一种基于计算机视觉技术的智能监测设备&#xff0c;它能够快速准确地识别出人们是否佩戴口罩&#xff0c;并对佩戴口罩的人员进行识别和记录。这种摄像机在当前抗击病毒的背景下具有重要意义&#xff0c;在公共场所、医疗机构、交通枢纽等地方都有着广…

Gradle学习笔记:Gradle的使用方法

文章目录 1.初始化项目2.构建脚本语言选择3.项目命名4.项目构建过程 1.初始化项目 创建一个test空文件夹&#xff0c;在该文件夹下打开终端&#xff0c;并执行命令&#xff1a;gradle init. 会有一个选项让你选择项目的类型。下面是每个选项的含义和用途&#xff1a; basic&am…

cg插画设计行业怎么样,如何学习插画设计

插画设计行业是一个充满创意和艺术性的行业&#xff0c;随着数字化时代的不断发展&#xff0c;cg插画的应用范围越来越广泛&#xff0c;市场需求也在逐年增长。以下是一些关于acg插画设计行业的现状和发展趋势&#xff1a; 市场需求不断增长&#xff1a;随着广告、媒体、影视、…

图像读写(imgcodecs 模块)与视频读写

内置格式 OpenCV 可以在没有任何第三方库帮助的情况下读取以下格式&#xff1a; BMP的 高动态范围 (WITH_IMGCODEC_HDR) 太阳栅格 (WITH_IMGCODEC_SUNRASTER) PPM、PGM、PBM、PFM&#xff08;、WITH_IMGCODEC_PXMWITH_IMGCODEC_PFM) PNG、JPEG、TIFF、WEBP 支持 格式选择…

C语言第九弹---二维数组

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 二维数组 1、二维数组的创建 1.1、二维数组的概念 ​1.2、⼆维数组的创建 2、二维数组的初始化 2.1、不完全初始化 ​2.2、完全初始化 ​2.3、按照行初始化 ​2.4、…

C++实用教程(四):面向对象核心多态 笔记

推荐B站视频&#xff1a;C现代实用教程(四):面向对象核心多态_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV15v4y1M7fF/?spm_id_from333.999.0.0&vd_sourcea934d7fc6f47698a29dac90a922ba5a3 本项目通用的tasks.json文件和launch.json tasks.json {"versi…

TMS智慧园区物流系统:提升化工园区管理效率的最佳选择

在化工行业园区中&#xff0c;企业面临着诸多痛点&#xff0c;如人工管理流程复杂、园区堵车、园区安全管理不到位、设备资产管理缺失、环境管理混乱无章、数据无法追溯等。这些问题不仅影响企业的生产效率和经济效益&#xff0c;还可能对员工的生命安全和环境造成潜在威胁。为…

uniapp封装公共的方法或者数据请求方法

仅供自己参考&#xff0c;不是每个页面都用到这个方法&#xff0c;所以我直接在用到的页面引用该公用方法&#xff1a; 1、新建一个util.js文件 export const address function(options){return new Promise((resolve,reject)>{uni.request({url:"https://x.cxniu.…

C# 命名管道管道NamedPipeServerStream使用

NamedPipeServerStream 是 .NET Framework 和 .NET Core 中提供的一个类&#xff0c;用于创建和操作命名管道的服务器端。命名管道是一种在同一台计算机上或不同计算机之间进行进程间通信的机制。 命名管道允许两个或多个进程通过共享的管道进行通信。其中一个进程充当服务器&…

CentOS网络配置进阶:深入研究network服务和NetworkManager

前言 如果你正在使用CentOS系统,并且想要深入了解网络管理和配置,那么本文肯定适合你!在这篇文章中,作者深入探讨了CentOS中的两种网络管理方式:network服务和NetworkManager。通过详实的讲解和实用的示例,你将会学习到如何使用这两种工具来管理网络接口、配置IP地址、网…

外贸邮件群发软件有哪些?邮件群发的系统?

外贸邮件群发软件哪个比较好&#xff1f;外贸开发信软件推荐&#xff1f; 对于许多外贸企业来说&#xff0c;邮件营销是一种非常有效的推广方式。那么&#xff0c;外贸邮件群发软件就成为了必备的工具。蜂邮EDM将为你揭秘几款主流的外贸邮件群发软件&#xff0c;助你更好地开展…

用javadoc生成springboot的文档

概述&#xff1a;生成 Spring Boot 项目的 JavaDoc 文档与生成普通的 Java 项目类似。 目录 第一步&#xff1a;创建一个springboot项目 第二步&#xff1a;编写pom文件 第三步&#xff1a;运行 Maven 命令生成 JavaDoc 第四步&#xff1a;查看结果 第一步&#xff1a;创建…

海外媒体发稿:出口贸易媒体发稿推广8种方法让您事半功倍-华媒舍

通过出口贸易媒体发稿可以帮助企业拓展市场、提升知名度&#xff0c;从而取得更好的出口贸易业绩。在进行媒体发稿时&#xff0c;需要确定目标受众&#xff0c;编写吸引人的标题&#xff0c;提供有价值的内容&#xff0c;并选择合适的媒体平台和发布时间。通过持续改进和优化&a…

自然语言NLP学习

2-7 门控循环单元&#xff08;GRU&#xff09;_哔哩哔哩_bilibili GRU LSTM 双向RNN CNN 卷积神经网络 输入层 转化为向量表示 dropout ppl 标量 在物理学和数学中&#xff0c;标量&#xff08;Scalar&#xff09;是一个只有大小、没有方向的量。它只用一个数值就可以完全…

docker之部署青龙面板

青龙面板是一个用于管理和监控 Linux 服务器的工具&#xff0c;具有定时运行脚本任务的功能。在实际情况下也可以用于一些定期自动签到等任务脚本的运行。 本次记录下简单的安装与使用&#xff0c;请提前安装好docker&#xff0c;参考之前的文章。 一、安装部署 1、拉取镜像 # …

小迪安全21WEB 攻防-JavaWeb 项目JWT 身份攻击组件安全访问控制

#知识点&#xff1a; 1、JavaWeb 常见安全及代码逻辑 2、目录遍历&身份验证&逻辑&JWT 3、访问控制&安全组件&越权&三方组件 Java&#xff1a;大部分都是第三方插件出现漏洞 webgoat的搭建&#xff1a;——java靶场 JDK版本要求&#xff1a;11.0…