[SpringBoot3]基础篇

二、SpringBoot基础篇

2.1什么是SpringBoot

  • SpringBoot是目前流行的微服务框架,倡导“约定优于配置”,其目的是用来简化新Spring应用的初始化搭建以及开发过程。
  • SpringBoot提供了很多核心的功能,比如自动化配置starter(启动器)简化Maven配置、内嵌Servlet容器、应用监控等功能,让我们可以快速构建企业级应用程序。
  • 特性:
    • 创建独立的Spring应用程序
    • 嵌入式Tomcat、Jetty、Undertow容器(jar)
    • 提供的starters简化构建配置(简化依赖管理和版本控制)
    • 尽可能自动配置spring应用和第三方库
    • 提供生产指标,例如指标、健壮检查和外部化配置
    • 没有代码生成,无需XML配置
  • SpringBoot同时提供“开箱即用”,“约定优于配置”的特性。
  • 开箱即用:SpringBoot应用无需从0开始,使用脚手架创建项目。基础配置已经完成。集成大部分第三方库对象,无需配置就能使用。例如在SpringBoot项目中使用MyBatis,可以直接使用XXXMapper对象,调用方法执行sql语句。
  • 约定优于配置:SpringBoot定义了常用类,包的位置和结构,默认的设置。代码不需要做调整,项目能够按照预期运行。比如启动类在根包的路径下,使用了@SpringBooApplication注解,创建了默认的测试类,controller、service、dao应该放到根包的子包中,application为默认的配置文件。
  • 脚手架(spring提供的一个web应用,帮助开发人员,创建springboot项目)
  • SpringBoot3最小JDK17,支持17-20。
  • SpringBoot理念”约定优于配置“,也可以称为按约定编程。

2.1.1SpringBoot与Spring关系

  • SpringBoot创建的是Spring应用,这里的Spring是指Spring Framework。
  • 我们常说的Spring,一般指的是Spring家族,包括Spring Boot、Spring Framework、Spring Data、Spring Security、Spring Batch、Spring Shell、Spring for Apache Kafka…。
  • SpringBoot是包含了Spring、SpringMVC的高级框架,提供了自动功能。能够更好的创建Spring应用,消除了Spring的XML配置文件,提高了开发效率,消除Spring应用的臃肿,避免了大量的模板代码。
  • SpringBoot是现在Java开发人员必须掌握的框架,SpringBoot是掌握SpringCloud的基础。

2.1.2SpringBoot3新特性

  • JDK最小Java17,能够支持17-20。
  • SpringBoot3已将所有底层依赖项从JavaEE迁移到了Jakarta EE API。原来javax开头的包名修改为jakarta。
  • 支持GraalVM原生镜像,将Java应用编译为本机代码,提供显著的内存和启动性能改进。
  • 对第三方库更新了版本支持。
  • 自动配置文件的修改。
  • 提供新的声明式Http服务,在接口方法上声明@HttpExchange获取http远程访问的能力。
  • Spring HTTP客户端提供基于Micrometer的可观察性跟踪服务,记录服务运行状态等。
  • 支持AOT预先编译。
  • Servlet6.0规范。
  • 支持Jackson2.14。
  • SpringMVC:默认情况下使用的PathPatternParser,删除过时的文件和FreeMarker、JSP支持。

2.2脚手架

  • 脚手架是辅助创建程序的工具,Spring Initializr是创建Spring Boot项目的脚手架,快速建立Spring Boot项目的最好方式。
  • 它是一个web应用,能够在浏览器中使用。
  • IDEA中继承了此工具,用来快速创建SpringBoot项目已经SpringCloud项目。
  • Spring Initializr 脚手架的 web 地址: https://start.spring.io/

2.2.1使用脚手架创建项目

  • 浏览器访问脚手架,创建项目

在这里插入图片描述

  • IDEA中使用脚手架

2.2.2IDEA创建SpringBoot项目

在这里插入图片描述

2.3代码结构

2.3.1单一模块

  • 一个工程一个模块的完整功能实现,例如实现订单功能。

com.example.模块名称

​ ±—Application.java 启动类

​ ±—controller 控制器包

​ —StudentController.java

​ —ScoreController.java

​ ±—service 业务层包

​ —inter 业务层接口

​ —impl 接口实现包

​ ±—repository 持久层包

​ ±—model 模型包

​ —entity 实体类包

​ —dto 数据传输包

​ —vo 视图数据包

2.3.2多个模块

  • 一个SpringBoot中多个模块,在根包下面创建每个模块的子包,子包中可以按照”单一模块“包结构定义。

2.3.3spring-boot-starter-parent

  • pom中的指定spring-boot-starter-parent作为坐标,表示继承SpringBoot提供的父项目。

  • 父项目提供以下功能:

    • JDK的基准版本,比如<java.version>17</java.version>
    • 源码使用UTF-8格式编码
    • 公共依赖的版本
    • 自动化的资源过滤:默认把src/main/resources目录下的文件进行资源打包
    • maven的占位符为’@’
    • 对多个Maven插件做了默认配置,如maven-compile-plugin,maven-jar-plugin
  • 快速创建SpringBoot项目,同时能够使用父项目带来的便利性,可以采用如下两种方式:

    1. 在项目中继承spring-boot-starter-parennt
    <!--parent:表示父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.2</version>
        <relativePath/>
    </parent>
    
    1. pom.xml不继承,单独加入spring-boot-dependencies依赖
    <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>3.1.2</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
    </dependencyManagement>
    

2.4starter

  • starter是一组依赖的描述,应用中包含starter,可以获取spring相关技术的一站式的依赖和版本。不必复制、粘贴代码,通过starter能够快速启动并运行项目。
  • starter包含:
    • 直接依赖坐标、版本
    • 传递依赖的坐标、版本
    • 配置类、配置项

pom.xml加入spring Web依赖

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

查看Maven依赖

Mybatis配置类
在这里插入图片描述

2.5@SpringBootApplication核心注解

/**
 * 核心注解的功能
 * @SpringBootConfiguration:包含@Configuration注解的功能
 * @Configuration:JavaConfig的功能,配置类,结合@Bean能够将对象注入到spring的IOC容器。
 * 有@SpringBootConfiguration标注的类是配置类,Springboot06PackageApplication就是配置类。
 *
 * @EnableAutoConfiguration:开启自动配置,将spring和第三方库中的对象创建好,注入到spring容器。
 * 避免写xml,去掉样例代码,需要使用的对象由框架提供。
 *
 * @ComponentScan:组件扫描器,<context:component-scan base-package="xxx包"/>
 * 扫描@Controller、@Service、@Repository、@Component注解,创建他们的对象注入到容器
 * springboot约定:启动类作为扫描包的根(起点),@ComponentScan扫描com.hhb.pk这个包和它的子包中所有的类
 *
 */
@SpringBootApplication
public class Springboot06PackageApplication {

    @Bean
    public Date myDate(){
        return new Date();
    }

    public static void main(String[] args) {
        //run方法的第一个参数是 源(配置类),从这里加载bean,找到bean注入到spring的容器。
        //run方法的返回值是容器对象
     ApplicationContext applicationContext= SpringApplication.run(Springboot06PackageApplication.class, args);

     //可以从容器获取对象
        Date date = applicationContext.getBean(Date.class);
    }
}
@RestController
public class HelloController {
    @Autowired
    private Date date;

    @GetMapping("/hello")
    public String hello() {
        return "欢迎使用SpringBoot3"+date;
    }
}

2.6运行SpringBoot项目方式

  • 开发工具,例如IDEA执行main方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jixTLi0f-1691849956073)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230810124122259.png)]

  • Maven插件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-du9bnuw9-1691849956074)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230810124207171.png)]

  • java -jar

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Po8aQ7j-1691849956074)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230810124302282.png)]

  • Spring Boot项目可以打包为jar或者war文件,因为SpringBoot内嵌了web服务器,例如tomcat。能够以jar方式运行web应用,无需安装tomcat程序。

普通的jar与SpringBoot jar的区别

项目springboot jar普通的jar
目录BOOT-INF:应用的class和依赖jar META-INF:清单 org.springframeword.boot.loader:spring-boot-loader模板类META-INF:清单 class的文件夹:jar中的所有类
BOOT-INFclass:应用的类 lib:应用的依赖没有BOOT-INF
spring-boot-loader执行jar的spring boot类没有此部分
可执行

2.7外部化配置

2.7.1配置文件基础

2.7.1.1 配置文件格式
  • 配置文件由两个种格式,分别是:properties和yaml(yml)。
  • properties是Java种常用的一种配置文件格式,基本的语法 key=value。可以是唯一的,文件扩展名是properties。
  • yaml也看做yml,是一种做配置文件的数据格式,基本的语法 key: value。yml文件扩展名是yaml或yml(常用)。
  • yaml基本语法规则:
    • 大小写敏感
    • 使用缩进表示层级关系
    • 缩进只可以使用空格,不允许使用Tab键
    • 缩进的空格数目不重要,相同层级的元素左侧对齐即可
    • #字符表示注释,只支持单行注释。#放在注释行的第一个字符
  • YAML缩进必须使用空格,而且区分大小写,建议编写YAML文件只用小写和空格。
  • YAML支持三种数据结构:对象、数组、标量
2.7.1.2application文件
  • SpringBoot同时支持properties和yml格式的配置文件,配置文件名称默认是application,我们可以使用application.properties,application.yml。
  • SpringBoot建议使用一种格式的配置文件,如果properties和yml都存在,优先读取properties文件,但是推荐使用yml文件。
  • application配置文件的名称和位置都可以修改,约定名称为application,位置为resources目录。
2.7.1.3application.properties

1.在application.properties自定义配置项目

#默认的配置文件:application.properties
app.name=springboot07
app.owner=hhb
app.port=8091

2.创建SomeService类读取key

  • @Value读取单个值,语法为 ${key:默认值}
@Service
public class SomeService {
    //使用@Value("${key:默认值}")

    @Value("${app.name}")
    private String name;

    @Value("${app.owner}")
    private String owner;

    @Value("${app.port:8080}")
    private Integer port;

    public void printValue() {
        StringJoiner joiner = new StringJoiner(";");
        String result = joiner.add(name).add(owner).add(String.valueOf(port)).toString();

        System.out.println("result=" + result);
    }
}

3.单元测试

@SpringBootTest
class Springboot07ConfigApplicationTests {

    @Autowired
    private SomeService someService;

    @Test
    void test() {
        someService.printValue();
    }

}
2.7.1.4application.yml

1.编写application.yml

#编写配置项 key: 值
app:
  name: springboot07
  owner: hhb07
  port: 9000
  • SpringBoot对yml文件的内容进行扁平化处理,将yml中的内容看做properties中的格式一样处理。也就是app: name 看做是app.name。所以在SpringBoot中认为properties和yml是一样的。

2.创建SomeService类读取key

  • @Value读取单个值,语法为 ${key:默认值}
@Service
public class SomeService {
    //使用@Value("${key:默认值}")

    @Value("${app.name}")
    private String name;

    @Value("${app.owner}")
    private String owner;

    @Value("${app.port:8080}")
    private Integer port;

    public void printValue() {
        StringJoiner joiner = new StringJoiner(";");
        String result = joiner.add(name).add(owner).add(String.valueOf(port)).toString();

        System.out.println("result=" + result);
    }
}

3.单元测试

@SpringBootTest
class Springboot07ConfigApplicationTests {

    @Autowired
    private SomeService someService;

    @Test
    void test() {
        someService.printValue();
    }

}
2.7.1.5Environment
  • Environment是外部化的抽象,是多种数据来源的集合。从中可以读取application配置文件、环境变量、系统属性。
  • 使用方式在Bean中注入Environment,调用它的getProperty(key)方法。

1.创建ReadConfig类,注入Environment

@Service
public class ReadConfig {
    //注入环境对象
    @Autowired
    private Environment environment;

    public void print() {
        //获取某个key的值
        String name = environment.getProperty("app.name");

        //判断key是否存在
        if( environment.containsProperty("app.owner")){
            System.out.println("app.owner是存在的");
        }

        //读取key的值,转为期望的类型,同时提供默认值
        Integer port = environment.getProperty("app.port", Integer.class, 9001);

        String format = String.format("读取的key值,name=%s,port=%d", name, port);
        System.out.println("str=" + format);
    }
}

单元测试

@SpringBootTest
class ReadConfigTest {
	@Autowired
	private ReadConfig readConfig;
	@Test
	void test01() {
		readConfig.print();
	}
}
2.7.1.6组织多文件
  • 大型集成的第三方框架,中间件比较多,每个框架的配置细节相对复杂,如果都将配置集中到一个application文件,导致文件内容多,不易阅读。我们将每个框架独立一个配置文件,最后将多个文件集中到application,我们使用导入文件的功能。

1.在resources创建自定义conf目录,在conf中创建redis.yml,db.yml

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J7LGv1Y4-1691849956074)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230810220657687.png)]

2.application.yml导入多个配置

#导入其他的配置 , 多个文件使用",“ 作为分隔符
spring:
  config:
    import: conf/db.yml,conf/redis.yml

3.创建类,读取两个文件的配置项

@Service
public class MultiConfigService {

    @Value("${spring.redis.host}")
    private String redisHostName;

    @Value("${spring.datasource.url}")
    private String jdbcUrl;

    public void print() {
        String format = String.format("redisHostName=%s,url=%s", redisHostName, jdbcUrl);
        System.out.println(format);
    }
}

4.单元测试

@SpringBootTest
class MultiConfigServiceTest {
	@Autowired
	private MultiConfigService multiConfigService;
	@Test
	void test01() {
		multiConfigService.printConfig();
	}
}
2.7.1.7多环境配置
  • SpringBoot规定环境文件的名称 application-{profile}.properties(yml)。其中profile为自定义的环境名称,推荐使用dev表示开发,test表示测试,prod表示生产,feature表示特性。
  • SpringBoot会加载application以及application-{profile}两类文件,不是只单独加载application-{profile}。

1.在resources创建环境配置文件

2.激活环境

  • spring.profiles.active: 环境名称
spring:
  #激活某个配置文件(环境)
  profiles:
    active: dev

3.创建读取配置项的类

@Service
public class MultiEnvService {
    @Value("${myapp.memo}")
    private String memo;

    public void print() {
        System.out.println("memo=" + memo);
    }
}

4.单元测试

@SpringBootTest
class MulitEnvServiceTest {
	@Autowired
	private MulitEnvService service;
	@Test
	void test01() {
		service.print();
	}
}

2.7.2绑定Bean

  • @Value绑定单个属性,当属性较多不方便时,SpringBoot提供了另一种绑定属性的方法。
  • 基本原则:标准的Java Bena有无参数构造方法,包含属性的访问器,配合@ConfigurationProperties注解一起使用,Bean的static属性不支持。
  • @ConfigurationProperties能够配置多个简单类型属性,同时支持Map、List、数组类型。对属性还能验证基本格式。
2.7.2.1简单的属性绑定

1.查看application配置

#编写配置项 key: 值
app:
  name: springboot07
  owner: hhb07
  port: 9000

2.创建Bean,定义name、owner、port属性

@Configuration(proxyBeanMethods = false)
@ConfigurationProperties(prefix = "app")
public class AppBean {
	private String name;
	private String owner;
	private Integer port;
	// set | get 方法 ,toString()
}
  • @ConfigurationProperties声明在类上,表示绑定属性到此类。prefix表示前缀,是配置文件中多个key的公共前缀。prefix=“app”,将文件中app开始的key都找到,调用与key相同名称的setXXX方法,如果有给属性赋值成功,没有的忽略。

单元测试

@Autowired
private AppBean appBean;

@Test
void test05() {
    System.out.println("appBean = " + appBean.toString());
    System.out.println("appBean.getClass() = " + appBean.getClass());
}
2.7.2.2嵌套Bean
  • Bean中包含其它Bean作为属性

1.定义两个Bean

public class Security {
	private String username;
	private String password;
	// set | get 方法 ,toString()
}
@Configuration(proxyBeanMethods = false)
@ConfigurationProperties(prefix = "app")
public class NestAppBean {
	private String name;
	private String owner;
	private Integer port;
	private Security security;
	// set | get 方法 ,toString()
}

2.定义application.yml

#yml 配置文件 key: 值
app:
	name: Lession07-yml
	owner: bjpowernode
	port: 8002
# app.security.username=root
# app.security.password=123456
security:
	username: root
	password: 123456
2.7.2.3扫描注解
  • @ConfigurationProperties注解起作用,还需要@EnableConfigurationProperties 或@ConfigurationPropertiesScan。这个注解是专门寻找@ConfigurationProperties 注解的,将他的对象注入到 Spring 容器。在启动类上使用扫描注解。
//扫描注解的包名,其中绑定Bean注入到Spring容器
@ConfigurationPropertiesScan(basePackages = {"com.hhb.config.pk6","com.hhb.config.pk8"})

//启用ConfigurationProperties,属性是类的名字
//@EnableConfigurationProperties({NestAppBean.class})
@SpringBootApplication
public class Springboot07ConfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot07ConfigApplication.class, args);
    }

}
2.7.2.4处理第三方库对象
  • 上面的例子都是在源代码中使用@ConfigurationProperties 注解,如果某个类需要在配置文件中提供数据,但是没有源代码。此时@ConfigurationProperties 结合@Bean 一起在方法上面使用。

1.application.yml添加新的配置

security:
	username: common
	password: abc123

2.创建配置类

@Configuration
public class ApplicationConfig {

    //创建bean对象,属性值来自配置文件
    @ConfigurationProperties(prefix = "security")
    @Bean
    public Security createSecurity(){
        return new Security();
    }
}

3.单元测试

@Autowired
private Security security;

@Test
void test07() {
    System.out.println("security.toString() = " + security.toString());
}
2.7.2.5集合Map、List以及Array
  • Map、List以及Array都能提供配置数据。

1.创建保存数据的Bean

public class User {
	private String name;
	private String sex;
	private Integer age;
	//set | get ,toString
}
public class MyServer {
	private String title;
	private String ip;
	//set | get ,toString
}
@Configuration
@ConfigurationProperties
public class CollectionConfig {
	private List<MyServer> servers;
	private Map<String,User> users;
	private String [] names;
	//set | get ,toString
}

2.修改application.yml,配置数据

#配置集合
#数组和List一样,使用“-”表示一个成员
names:
  - 李四
  - 张三
##List<MyServer> servers
servers:
  - title: 服务器1
    ip: 101.12.36.2
  - title: 服务器2
    ip: 202.90.23.263
#Map<String,User> users
users:
  user1:
    name: 张三
    sex:age: 22
  user2:
    name: 李四
    sex:age: 23
  • “-”表示集合一个成员,因为成员是对象,需要属性名称指定属性值。
  • List与数组前面加入“-”表示一个成员。
  • Map直接指定key和value,无需“-”。

3.单元测试

@Autowired
private CollectionConfig collectionConfig;

@Test
void test08() {
    System.out.println("collectionConfig.toString() = " + collectionConfig.toString());
}
2.7.2.7指定数据源文件
  • application做配置是经常使用的,除此之外我们能够指定某个文件作为数据来源。
  • @PropertySource是注解 ,用以加载指定的properties文件、yml文件。@PropertySource与@Configuration一同使用,其它注解还有@Value,@ConfigurationProperties。

1.创建Group类,表示组织

@Configuration
@ConfigurationProperties(prefix = "group")
@PropertySource(value = "classpath:/group-info.properties")
public class Group {
	private String name;
	private String leader;
	private Integer members;
	//set | get ,toString
}

2.在resources目录下的任意位置创建properties文件

group.name=IT学习专栏
group.leader=无名
group.members=20

总结

  • @ConfigurationProperties绑定Bean对于使用配置文件的数据十分方便、灵活的。

2.8创建对象三种方式

  • 将对象注入到Spring容器,可以通过如下方式:

    • 传统的XML配置文件
    • Java Config技术,@Configuration与@Bean
    • 创建对象的注解,@Controller ,@Service , @Repository ,@Component
  • Spring Boot不建议使用XML文件的方式,自动配置已经解决了大部分XML中的工作了。如果需要XML提供bean的声明,@ImportResource加载XML注册Bean。

1.创建Person类,对象由容器管理

public class Person {
	private String name;
	private Integer age;
	//set | get ,toString
}

2.resources目录下创建XML配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--声明Bean对象-->
    <bean id="myPerson" class="com.hhb.config.pk10.Person">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
    </bean>
</beans>

3.启动类,从容器中获取Person对象

//在配置类加入注解@ImportResource
@ImportResource(locations = {"classpath:/applicationContext.xml"})
@SpringBootApplication
public class Springboot07ConfigApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(Springboot07ConfigApplication.class, args);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println("bean = " + bean);
    }

}
  • @ImportResource(locations = {“classpath:/applicationContext.xml”}),加载类路径下的applicationContext.xml文件。location或者value属性都能指定文件路径。

2.9AOP

  • AOP:面向切面编程,保持原有代码不变,能够给原有的业务逻辑增加更多功能。

  • AOP增加的功能是开发人员自己编写的,底层是动态代理实现功能的增强,对于扩展功能十分有利。

  • Spring的事务功能就是在AOP基础上实现的,业务方法在执行前开启事务,再执行业务方法,最后提交或回滚失败。

  • 主要包括五个注解:@Before、@After、@AfterReturning、@AfterThrowing、@Around。注解来自aspectj框架。

    • @Before:在切点方法之前执行。
    • @After:在切点方法之后执行。
    • @AfterReturning:切点方法返回后执行。
    • @AfterThrowing:切点方法抛异常执行。
    • @Around:属于环绕增强,能控制切点执行前、执行后,功能最强的注解。
  • 需求:项目中的业务方法都需要在日志中输出方法调用的时间以及参数明细。业务方法多,使用AOP最合适。

1.Maven添加aop依赖

  • 包含了aop和aspectj依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.创建业务类SomeService在aop的service子包

public interface SomeService {
    void query(Integer id);

    void save(String name, Integer age);
}
@Service
public class SomeServiceImpl implements SomeService {
    @Override
    public void query(Integer id) {
        System.out.println("SomeService业务方法query");
    }

    @Override
    public void save(String name, Integer age) {
        System.out.println("SomeService业务方法save");
    }
}

3.创建切面类

  • @Aspect说明当前类是切面类,包含了功能增强的代码和通知注解。
  • @Component将切面类对象注入到spring容器。spring会根据目标类和切面类创建代理对象,织入切面功能。
@Component
@Aspect
public class LogAspect {

    //功能增强的方法
    @Before("execution(* com.example.aop.service.*.*(..))")
    public void sysLog(JoinPoint joinPoint) {
        StringJoiner log = new StringJoiner("|", "{", "}");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        log.add(sdf.format(new Date()));

        //当前执行的业务方法名称
        String name = joinPoint.getSignature().getName();
        log.add(name);

        //方法的参数
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            log.add(arg == null ? "-" : arg.toString());
        }
        System.out.println("日志:" + log);
    }
}

4.单元测试

@SpringBootTest
class Springboot08AopApplicationTests {

    @Autowired
    private SomeService someService;

    @Test
    void testAspect() {
        someService.query(null);
        someService.save("张三", 20);
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微服务与Nacos概述-2

微服务间消息传递 微服务是一种软件开发架构&#xff0c;它将一个大型应用程序拆分为一系列小型、独立的服务。每个服务都可以独立开发、部署和扩展&#xff0c;并通过轻量级的通信机制进行交互。 应用开发 common模块中包含服务提供者和服务消费者共享的内容 provider模块是…

Ansible的安装和配置

安装和配置 Ansible 安装所需的软件包 创建名为 /home/greg/ansible/inventory 的静态清单文件&#xff0c;以满足以下要求&#xff1a; 172.25.250.9 是 dev 主机组的成员 172.25.250.10 是 test 主机组的成员 172.25.250.11 和 172.25.250.12 是 prod 主机组的成员 172.2…

闭环控制方法及其应用:优缺点、场景和未来发展

闭环控制是一种基本的控制方法&#xff0c;它通过对系统输出与期望值之间的误差进行反馈&#xff0c;从而调整系统输入&#xff0c;使系统输出更加接近期望值。闭环控制的主要目标是提高系统的稳定性、精确性和鲁棒性。在实际应用中&#xff0c;闭环控制有多种方法&#xff0c;…

深入浅出:MyBatis的使用方法及最佳实践

这里写目录标题 添加MyBatis框架⽀持配置连接字符串和MyBatis配置连接字符串配置 MyBatis 中的 XML 路径 添加业务代码创建数据库和表添加用户实体类添加 mapper 接⼝添加 UserMapper.xml添加 Service层添加 Controller层 增删改操作增加操作删除操作修改操作 添加MyBatis框架⽀…

无感部署 - 蓝绿部署、AB测试、灰度发布

蓝绿部署 蓝绿部署&#xff08;Blue-Green Deployment&#xff09;是一种软件发布和部署的策略&#xff0c;旨在实现无缝的应用程序升级和回滚。在蓝绿部署中&#xff0c;同时存在两个环境&#xff1a;一个是当前稳定的生产环境&#xff08;蓝色环境&#xff09;&#xff0c;另…

Spring Cloud 智慧工地源码(PC端+移动端)项目平台、监管平台、大数据平台

智慧工地源码 智慧工地云平台源码 智慧建筑源码 “智慧工地”是利用物联网、人工智能、云计算、大数据、移动互联网等新一代信息技术&#xff0c;彻底改变传统建筑施工现场参建各方现场管理的交互方式、工作方式和管理模式&#xff0c;实现对人、机、料、法、环的全方位实时监…

国产航顺HK32F030M: 基于NTC负温度系数的温度计

前言&#xff1a; 家里的一个儿童澡盆附带的温度计坏掉了&#xff0c;拆解后发现这东西做的真垃圾&#xff01;索性自己做一个。拆下了里面的NTC热敏电阻&#xff0c;但是不知道NTC的性能参数&#xff0c;经过测量与查资料后&#xff0c;采用用中位值滤波 、 Steinhart-Hart方…

swagger 3.0 学习笔记

引入pom <dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version></dependency>配置 import io.swagger.models.auth.In; import io.swagger.v3.oas.annotati…

三级城市展示省市区树

展示效果 数据库展示 业务代码 /*** 省市区树*/VLicenseApiOperation("查询经纬度")ApiImplicitParam(name "FnCity", value "省市区树", dataType "FnCity")GetMapping("/districtlist")public AjaxResult districtlist…

strlen和sizeof的区别

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解C语言中的sizeof和strlen&#xff08;仅此一篇让你明白它们两的差别&#xff09;&#xff0c;如果大家觉得我写的不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 文章目录 strlensizeof 在…

Simulink仿真模块 -Scope

Scope模块的作用是显示仿真过程中生成的信号。它包含在以下库中: 库: Simulink / Commonly Used BlocksSimulink / SinksHDL Coder / Commonly Used BlocksHDL Coder / Sinks 如图所示: Simulink Scope 模块和 DSP System Toolbox™ Time Scope 模块显示时域信号。…

【APITable】教程:创建并运行一个自建小程序

1.进入APITable&#xff0c;在想要创建小程序的看板页面点击右上角的【小程序】&#xff0c;进入小程序编辑页面。 2.创建一个新的小程序区。 点击【 添加小程序】 点击创建小程序&#xff0c;选择模板&#xff0c;输入名字。 3.确定后进入小程序部署引导页面。 4.打开Xshell 7…

春秋云镜 CVE-2022-0410

春秋云镜 CVE-2022-0410 WordPress plugin The WP Visitor Statistics SQLI 靶标介绍 WordPress plugin The WP Visitor Statistics (Real Time Traffic) 5.6 之前存在SQL注入漏洞&#xff0c;该漏洞源于 refUrlDetails AJAX 不会清理和转义 id 参数。 登陆账户&#xff1a;u…

LeetCode 热题 100 JavaScript -- 74. 搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非递减顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 …

D* 算法完全解析(应该是全网最详细的吧)

花了几天时间学习了下 D* 算法&#xff0c;只能说熟悉了一下流程&#xff0c;远不能说掌握&#xff0c;算法实在是非常巧妙 参考 《制造车间无人搬运系统调度方法研究》 《基于D*Lite算法的移动机器人路径规划研究》 人工智能: 自动寻路算法实现(四、D、D*算法) D* 算法 D*路径…

java 文件/文件夹复制,添加压缩zip

复制文件夹,并压缩成zip 需求&#xff1a;创建A文件夹&#xff0c;把B文件夹复制到A文件夹。然后把A文件夹压缩成zip包 public static void main(String[] args) throws Exception {try {String A "D:\\dev\\program";String B "D:\\program";// 创建临…

iOS- git对单个或者多个文件权限设置,使用pre-commit hook 和shell脚本,拦截校验

前提&#xff1a;最近&#xff0c;由于团队代码规范和安全问题&#xff0c;有一些文件只能是指定用户才能修改。 对比&#xff1a;调查了一下资料&#xff0c;发现好多人都在使用pre-commit技术。于是&#xff0c;就朝着这个方向去研究。于是抽空写了脚本&#xff0c;在提交的…

写一个函数返回参数二进制中 1 的个数(c语言三种实现方法)

&#xff08;本文旨在自己做题时的总结&#xff0c;我会给出不同的解法&#xff0c;后面如果碰到新的题目还会加入其中&#xff0c;等于是我自己的题库。 1.写一个函数返回参数二进制中 1 的个数。 比如&#xff1a; 15 0000 1111 4 个 1 方法一&#xff1a; #include…

form中表单切换,导致 relus 中的事件无法触发,原因:页面切换不要一直切换DOM,会导致问题,需要都显示出来

修改前&#xff0c;因为重复渲染DOM导致绑定rules失效 修改前代码使用 computed 计算出渲染的DOM&#xff0c;影响rules事件<el-formref"form"inline:model"billDetailCopy":rules"rules"size"small"label-position"right&quo…

WebStorm

WebStorm 介绍下载安装Activation 介绍 WebStorm是由JetBrains公司开发的一款集成开发环境&#xff08;IDE&#xff09;&#xff0c;主要专注于前端开发和Web开发。它旨在提供一套强大的工具和功能&#xff0c;以支持开发者在前端项目中编写、调试和维护代码。 JetBrains官网: …