🎉🎉《Spring Boot实战案例合集》目前已更新125个案例,我们将持续不断的更新。文末有电子书目录。
💪💪永久更新承诺
我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。
💌💌如何获取
订阅我们的合集《点我订阅》,并通过私信联系我们,我们将第一时间将电子书发送给您。
环境:SpringBoot3.4.2
1. @Lookup
该注解只能应用于方法上,用于指示“查找”方法的注解。
如何查找?
根据当前方法的返回值或者该注解配置的value属性值(beanName),在容器中查找对应的bean,通过BeanFactory#getBean进行备案的查找。如下示例:
首先,我们定义如下的原型Bean:
public class PrototypeBean {}
其次,定义使用@Lookup注解的bean:
public abstract class BusinessBean {public abstract PrototypeBean getInstance() ;}
最后,定义如下Runner进行测试:
public class LookupRunner implements CommandLineRunner {// 注入抽象类private final BusinessBean businessBean ;public LookupRunner(BusinessBean businessBean) {this.businessBean = businessBean;}public void run(String... args) throws Exception {System.err.println(this.businessBean.getInstance()) ;System.err.println(this.businessBean.getInstance()) ;System.err.println(this.businessBean.getInstance()) ;}}
运行结果
首先,Spring底层对我们的抽象类做了特殊处理(创建了代理,如果抽象类中没有使用@Lookup注解的方法,那么将会报错),当我们每次调用getInstance方法时都会通过BeanFactory#getBean从容器中获取bean,这样就确保了在单例bean中正确的获取多例bean。
有关@Lookup更多的详细介绍,请查看下面这篇文章:
使用 @DeclareParents 注解用于声明匹配的类型拥有一个新的父类型。简单点说,那些符合条件的类将会拥有一个新的父类(自动帮你实现一个指定的接口)。如下示例:
首先,我们定义一个接口及对应的实现类:
public interface DAO {void query() ;}public class CommonDAO implements DAO {public void query() {System.err.println("通用查询接口服务...") ;}}
其次,定义如下的一个类:
@Componentpublic class UserDAO {}
我们接下来要做的是定义切面,让UserDAO类自动的实现DAO接口,并且该接口的对应实现使用CommonDAO。
@Aspect@Componentpublic class DeclareParentsAspect {@DeclareParents(value = "com.pack.common_use.annotation.UserDAO", defaultImpl = CommonDAO.class)private DAO dao ;}
说明:value配置是Aspectj 切点表达式,这里将值匹配UserDAO。我们还可以使用如下的表达式:
# 匹配common_user包及其子包下的所有类com.pack.common_user.*+
注意,只支持类级别。
最后,通过如下的Runner测试:
public class DeclareParentsRunner implements CommandLineRunner {private final UserDAO userDAO ;public DeclareParentsRunner(UserDAO userDAO) {this.userDAO = userDAO;}public void run(String... args) throws Exception {if (userDAO instanceof DAO dao) {dao.query() ;}}}
运行结果
从Spring6.x起,Spring Web模块默认引入micrometer-core依赖(度量指标库),而这两个注解都是在该包中。这2个注解都对应的有一个Aspect切面,要启用这2个注解功能可以通过如下2种方式:
自定义对应的Bean对象TimedAspect,CountedAspect
引入actuator依赖,将自动的配置这2个切面(推荐)
接下来,我们将通过actuator的方式来演示:
首先,引入actuator依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
还需要开启如下配置:
management:observations:annotations:enabled: true
其次,定义如下的Controller接口:
public class TimedCountedAController {description = "统计执行时间",value = "exec_time",histogram = true,extraTags = {"pack", "time"})public ResponseEntity<?> time() throws Exception {TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000)) ;return ResponseEntity.ok("success") ;}public ResponseEntity<?> count() throws Exception {return ResponseEntity.ok("success") ;}}
接下来,我们随意的访问上面2个接口。然后,再访问/ac/metrics接口。
我们定义的2个指标已经在metrics端点中。
最后,分别查看这2个指标:
当接口发生异常,那么通过该指标端点也是可以查看的。
用于标识那些需要配置 @ConfigurationProperties 绑定(例如转换器 Converters)的 bean 的限定符。
现在有如下的配置类及配置属性值:
public class CommonProperties {private String author ;private App app ;// getters, setters}
配置文件:
pack:common:author: xxggapp: Spring Boot3实战案例200讲,1.0.0
类中app属性是App对象类型,而配置文件中则是由逗号分割的字符串,这在默认情况下是是无法进行转换的,如下错误:
在不修改配置属性方式的情况下,要解决该问题你可以自定义类型转换器,如下示例:
public class AppConverter implements Converter<String, App> {public App convert(String source) {if (source == null) {return null ;}String[] values = source.split(",") ;if (values.length < 2) {return null ;}return new App(values[0], values[1]) ;}}
该类使用了@ConfigurationPropertiesBinding注解(必须使用)。
定义了该特殊的ben后,容器在绑定属性值时就能通过该转换器进行处理了。
推荐文章
高级开发!Spring Boot处理枚举类型,支持JPA、MyBatis、Jackson
强大!基于Spring Boot通过责任链模式,实现复杂接口动态编排能力
性能调优实战:Spring Boot 通过多线程处理SQL IN语句大量值的优化方案
王炸!Spring AI+Tools 一分钟实现CRUD智能助手
注意!@ExceptionHandler异常处理注解有新功能了
高级开发!自定义组件通过3种方式解决Spring Boot配置文件中的敏感数据
如何在Spring Boot中优雅地加载配置?这些方法你必须掌握!


