POM文件中为何要以继承的方式引入SpringBoot?
继承父工程的优势
- 依赖管理:在父工程中定义依赖的版本,子模块直接引用而不必指定版本号
- 插件管理:在父工程中配置插件,子模块直接使用
- 属性设置:在父工程中定义一些通用属性,如项目编码、java版本等
- 统一配置:可以统一多个子模块的构建配置,确保一致性。
继承了父工程,那么引入依赖的时候不需要指定版本号,因为在父工程中,各种依赖的版本号已经预设好了。
SpringBoot核心注解
@SpringBootApplication
被此标注表示该类是SpringBoot项目的入口类。
此注解被以下三个注解标注,说明@SpringBootApplication同时有以下三个注解的功能
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan@SpringBootConfiguration
@SpringBootConfiguration被@Configuration标注说明项目的主入口类同时是一个配置类,因此在主入口类中使用@Bean注解方法的话,该方法返回值对象会被纳入Ioc容器管理。
@EnableAutoConfiguration
启用自动配置,SpringBoot默认情况下启用自动配置。
自动配置有什么用?
自动配置只要启动,SpringBoot就会去类路径中查找Class。根据类路径中有某些类来自动管理Bean,不需要程序员手动配置。
比如SpringBoot检测到SqlSessionFactory,或者在application.properties中配置了数据源,SpringBoot会认为项目中含有MyBatis框架,会将MyBatis相关的Bean初始化,然后放到Ioc容器中管理起来。
@ComponentScan
@ComponentScan负责组件扫描。会扫描此包及此包下所有子包或子包的子包等的路径。
外部化配置
外部化配置是指将配置信息存储 在应用程序代码之外的地方。这样配置信息独立于 代码进行管理。方便配置修改。修改后不需要重新编译,也不需要重新部署。
springboot默认先找外部化配置
Application.properites
Application.properites配置文件是SpringBoot默认的额配置文件
Application.properites不是必须的,SpringBoot提供了默认配置,如果需要修改默认配置,就在Application.properites中进行配置。
Application.properites可以放在类路径中,也可以放在项目之外,因此成为外部化配置
SpringBoot在启动时会从以下位置按顺序加载Application.properites:
- file:./config/: 首先在SpringBoot当前工作目录下的config文件夹中查找(如果没找到Application.properites,会继续查找Application.yml,2个都没找到,才会进入下一个位置查找,以此类推)
- file:./: 这里找不到会继续查找下一个位置
- classpath:/config/:
- classpath:/
如果在多个位置有相同属性的定义,那么最先检查的位置中的属性值先使用。
如果要指定配置文件位置,可以通过--spring.config.location=进行指定,比如:
/* by 01130.hk - online tools website : 01130.hk/zh/calculator.html */ java -jar xxxx.jar --spring.config.location=file:///E:\a\b\application.properties注意:以上的--spring.config.location=file:///E:\a\b\application.properties属于命令行参数,会被传递到main方法的(String[] args)参数上。
读取配置
/* by 01130.hk - online tools website : 01130.hk/zh/calculator.html */ // 读取配置文件中myapp.path的值, // 如果这个key不存在,并且没有指定默认值,那么会报错 // ${myapp.path:50}指定myapp.path的默认值是50 @Value("${myapp.path:50}") private String appPath;YAML语法规则
数据结构
支持多种数据结构,包括:字符串、数字、布尔值、数组、List集合、Map键值对等
yaml使用一个空格来分割属性名和属性值,比如:
name: jack- yaml使用换行+空格表示层级关系,注意不能使用tab 必须是空格,空格数量无要求,建议2个或4个,比如:
myapp: name: mall- 同级元素左侧对其
- 大小写敏感
- 使用# 进行注释
- 在一个映射中,键必须唯一
- 普通文本可以使用单引号,也可以使用双引号,也可以什么都不用(单引号中的\n表示普通文本,双引号中的\n表示换行)
- 保留文本原格式使用 | 比如:
username: | aaaa bbb ccc- 文档切割: --- 这个符号下面的配置认为是一个独立的yaml文件,便于大文件的阅读。
配置文件合并
#properties文件合并 # 对于数组来说,使用逗号进行分隔开 spring.config.import=classpath:/application-mysql.properties,classpath:/application-redis.propertiesyml文件合并的第一种写法
spring: config: import: [classpath:/application-mysql.yml,classpath:/application-redis.yml]yml文件合并的第二种写法
spring: config: import: - classpath:/application-mysql.yml - classpath:/application-redis.yml多环境切换
开发环境配置文件:application-dev.properties
测试环境配置文件:application-test.properties
预生产环境配置文件:application-preprod.properties
生产环境配置文件:application-prod.properties
如果启用生产环境配置,可以有以下两种操作方式:
- 在application.properties添加配置:spring.profiles.active=prod
- 在命令行参数上添加: --spring.profiles.active=prod
将配置绑定到简单Bean
package com.ali.bindtobean.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; // 纳入Ioc容器 @Component // 将配置文件一次性绑定到Bean对象上 @ConfigurationProperties(prefix = "myapp") public class AppConfig { // 要实现一次性绑定,配置文件中的属性名 必须和Bean对象的属性名要一致 // 底层在给对象属性赋值时,调用了setter方法,因此每个属性必须有setter方法 private String name; private Integer age; private String password; private Boolean gender; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Boolean getGender() { return gender; } public void setGender(Boolean gender) { this.gender = gender; } @Override public String toString(){ return "AppConfig [name=" + name + ", age=" + age + ", gender=" + gender + "]"; } }spring.application.name=bindtobean myapp.name=jack myapp.age=12 myapp.password=123 myapp.gender=true绑定嵌套Bean
在一个Bean的属性中,有一个其他Bean类型。这样就是嵌套Bean。
package com.ali.bindtobean.bean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "app.xyz") public class User { private String name; private Address address; public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User [name=" + name + ", address=" + address.toString() + "]"; } }package com.ali.bindtobean.bean; public class Address { private String city; private String street; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } @Override public String toString() { return "Address [city=" + city + ", street=" + street + "]"; } }app.xyz.name=lucy app.xyz.address.city=xj app.xyz.address.street=dayang其他方式绑定Bean
// 在主入口程序添加以下注解,启用将配置信息绑定到User这个Bean @EnableConfigurationProperties({User.class, Address.class})另一种方式:
// 在主入口程序添加以下注解,扫面指定包。将配置信息绑定到这个包下的类 @ConfigurationPropertiesScan(basePackages = "com.ali.bindtobean.bean")复杂的属性结构绑定Bean
绑定数组、集合、Map到Bean
app2.abc.names[0]=jack app2.abc.names[1]=lucy app2.abc.names[2]=tom app2.abc.addresses[0].city=bj app2.abc.addresses[0].street=chaoyang app2.abc.addresses[1].city=tj app2.abc.addresses[1].street=nankai app2.abc.addressList[0].city=bj_list app2.abc.addressList[0].street=chaoyang_list app2.abc.addressList[1].city=tj_list app2.abc.addressList[1].street=nankai_list # addr1 和addr2 都是key app2.abc.addressMap.addr1.city=bj_map app2.abc.addressMap.addr1.street=chaoyang_map app2.abc.addressMap.addr2.city=tj_map app2.abc.addressMap.addr2.street=nankai_mapyaml文件配置方式如下:
app2: abc: names: - tom - smith addresses: - city: beijing street: chaoyang - city: tianjin street: nankai # addressList 可以写成 address-list addressList: - city: beijing street: chaoyang - city: tianjin street: nankai addressMap: addr1: city: beijing street: chaoyang addr2: city: tianjin street: nankaipackage com.ali.bindtobean.bean; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.Map; @ConfigurationProperties(prefix = "app2.abc") public class AppBean { // 数组中元素是简单类型 private String[] names; // 数组中元素是Bean private Address[] addresses; //List集合。List中元素是Bean private List<Address> addressList; //Map集合: String,Bean private Map<String,Address> addressMap; public void setNames(String[] names) { this.names = names; } public void setAddresses(Address[] addresses) { this.addresses = addresses; } public void setAddressList(List<Address> addressList) { this.addressList = addressList; } public void setAddressMap(Map<String, Address> addressMap) { this.addressMap = addressMap; } @Override public String toString() { return ""; } }将配置绑定到第三方对象
other: abc: city: beijing street: daxingpackage com.ali.bindtobean.config; import com.ali.bindtobean.bean.Address; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig2 { // address 是第三方类,使用以下方式完成配置到属性的绑定 @Bean @ConfigurationProperties(prefix = "other.abc") public Address address() { return new Address(); } }指定配置数据来源
@Component @ConfigurationProperties(prefix = "app2.abc") // 指定配置数据来自/a/b/group-info.properties路径的配置文件 @PropertySource("classpath:/a/b/group-info.properties") public class AppBean { ... }@ImportResource注解
当SpringBoot项目中出现ApplicationContext.xml文件。并且文件中配置了Bean。要把这个Bean注入到容器中。
package com.ali.bindtobean.bean; public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return super.toString(); } }配置文件如下:
<?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 id="person" class="com.ali.bindtobean.bean.Person"> <property name="name" value="jack"/> <property name="age" value="20"/> </bean> </beans>// 在主入口程序添加以下注解让applocationContext.xml文件生效 @ImportResource("classpath:/applocationContext.xml")Environment
spring提供的一个接口。SpringBoot启动的时候会把环境、系统信息封装到Environment对象中,需要获取这些信息,可使用Environment接口的方法。
Environment对象主要包括
- 当前激活的配置文件 active-profiles
- 系统属性,如系统名字 、java版本
- 环境变量
- 应用程序启动时传给主方法的命令行参数
@Autowired private Environment environment; public void doSomething() { // 获取当前激活的配置文件 String[] activeProfiles = environment.getActiveProfiles(); for (String activeProfile : activeProfiles) { System.out.println(activeProfile); } // 获取配置信息 String property = environment.getProperty("app.xyz.address.city"); System.out.println(property); }SpringBoot aop实现
添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>3.3.5</version> </dependency>编写切面类
package com.ali.springaop.component; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.LoggerFactory; import org.slf4j.Logger; import org.springframework.stereotype.Component; import java.util.Arrays; // 指定切面类 @Aspect @Component public class LoggingAspect { private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class); // 定义切入点,匹配所有以“service”结尾的包下的所有方法 @Pointcut("execution(* com.ali.springaop.service..*(..))") public void ServiceMethods(){ } // 前置通知,切入点的方法执行前执行此代码 @Before("ServiceMethods()") public void before(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); logger.info("Method [{}] with parameters [{}] is called", methodName, Arrays.toString(args)); } }本文来自博客园,作者:NE_STOP,转载请注明原文链接:https://www.cnblogs.com/alineverstop/p/19506048