跳到主要内容

Spring Boot

Singleton Inject but need dynamic changing value

A bug finds in those of tasks where you need change the date by the nature.
Firstly You should inject a prototype bean to spring context, instead of injecting a singleton object; Secondly you need use this way.

@Component
public class SingletonService {

// 使用 ObjectFactory(也可以用 javax.inject.Provider 或 Spring 的 Provider)
@Resource
private ObjectFactory<PrototypeBean> prototypeBeanFactory;

public void callTest() {
PrototypeBean prototypeBean = prototypeBeanFactory.getObject();
prototypeBean.doSomething();
}
}

启动问题

Springboot启动时报错 org.springframework.boot不存在

建议采用方法二在终端中输入mvn idea:idea,方法一在Spring Boot 项目中,运行其他Main方法测试类的时候会重新启动SpringBoot 工程,如果你还从ApplicationContext中获取,那么将会收到报错容器已经关闭。 参见博客

spring boot源码运行SpringApplication时报错

Could not find artifact lifecycle-mapping:lifecycle-mapping:jar:sources:1.0.0 参见博客 已经要付费看了!无语

gradle spring boot 3.0 导入报错

无效的源发行版: 17

确保gradle的版本JDK 17 和 JDK 的版本正确。

image-20230728021351697

日志相关

启动控制台日志没有颜色

在spring-logback.xml中引入

<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springboot.sample" level="TRACE"/>

logback 修改日志打印内容

代码: extends ThrowableHandlingConverter impl convert 方法

logback配置

<conversionRule convertionWord="someKeyMsg" convertClass="com.xxx.xxx.Xclass"/>

打包问题

after run the packaged jar occurs this unable to find main class

方法1. 替换插件

<!--<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>none</mainClass>
<classifier>execute</classifier>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>

方法2: 去掉spring-boot parent,再使用spring boot plugin 打包


获取 AOP 代理对象的真实类注解

在 Spring Boot 中,使用 @Aspect 等 AOP 技术后,注入的 Bean 是代理对象。 直接通过 getClass().getAnnotation() 往往无法获取到原始类上的注解(尤其是 JDK 动态代理)。

核心解决方案:使用 Spring 提供的 AopProxyUtils 穿透代理,获取最终的原始业务类

点击查看
import org.springframework.aop.framework.AopProxyUtils;
// ...
@Component
public class MyAnnotationScanner implements ApplicationRunner {

private final ApplicationContext context;
private final Map<String, MyAnnotation> cacheMap = new ConcurrentHashMap<>();

public MyAnnotationScanner(ApplicationContext context) {
this.context = context;
}

@Override
public void run(ApplicationArguments args) {
// 1. 获取所有带有特定注解的 Bean
Map<String, Object> beans = context.getBeansWithAnnotation(MyAnnotation.class);

beans.forEach((name, bean) -> {
// 2. 穿透代理,获取真实的类(TargetClass)
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);

// 3. 提取注解信息
MyAnnotation anno = AnnotationUtils.findAnnotation(targetClass, MyAnnotation.class);

if (anno != null) {
cacheMap.put(targetClass.getName(), anno);
}
});
}
}
协议
本作品代码部分采用Apache 2.0协议 进行许可。遵循许可的前提下,你可以自由地对代码进行修改,再发布,可以将代码用作商业用途。但要求你:
  • 署名:在原有代码和衍生代码中,保留原作者署名及代码来源信息。
  • 保留许可证:在原有代码和衍生代码中,保留Apache 2.0协议文件。
本作品文档部分采用知识共享署名 4.0 国际许可协议 进行许可。遵循许可的前提下,你可以自由地共享,包括在任何媒介上以任何形式复制、发行本作品,亦可以自由地演绎、修改、转换或以本作品为基础进行二次创作。但要求你:
  • 署名:应在使用本文档的全部或部分内容时候,注明原作者及来源信息。
  • 非商业性使用:不得用于商业出版或其他任何带有商业性质的行为。如需商业使用,请联系作者。
  • 相同方式共享的条件:在本文档基础上演绎、修改的作品,应当继续以知识共享署名 4.0国际许可协议进行许可。