SpringBoot 컨테이너가 새로 고쳐지기 전에 ApplicationContextInitializer를 다시 호출하는 방법
I. 프로젝트 준비
이 기사에서 만든 예제 프로젝트는 SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ idea
를 사용하여 개발되었습니다. >SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ idea
进行开发
具体的SpringBoot项目工程创建就不赘述了,核心的pom文件,无需额外的依赖
配置文件 application.yml
, 也没有什么特殊的配置
II. 容器刷新前扩展点实例
1. 自定义ApplicationContextInitializer
当我们希望实现一个自定义的上下文初始化时,非常简单,实现上面这个接口就行了,如
public class ApplicationContextInitializer01 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer01"); } }
2. 扩展点注册
上面自定义一个扩展点,如何使它生效呢?
官方提供了三种方式,如在启动时,直接进行注册: springApplication.addInitializers(new ApplicationContextInitializer01());
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(Application.class); springApplication.addInitializers(new ApplicationContextInitializer01()); try (ConfigurableApplicationContext context = springApplication.run(args)) { } } }
当我们的扩展点是放在一个jar包中对外提供时,使用上面的启动注册方式显然是不可行的,此时更推荐的做法就是通过Spring的SPI机制进行注册
在资源目录下的META-INF/spring.factories
文件中进行注册
org.springframework.context.ApplicationContextInitializer=com.git.hui.extention.context.ApplicationContextInitializer02
说明
上面SPI的机制非常推荐大家使用,在之前的文章中,
AutoConfiguration
的注册通常也是使用这种方式
除了上面的两种注册方式之外,另外还有一个配置文件的方式,在配置文件application.properties
或 application.yml
中,如下配置
context: initializer: classes: com.git.hui.extention.context.ApplicationContextInitializer03
启动测试
上面三种注册方式,我们实现三个自定义的扩展点,然后启动之后,看一下实际输出
上面的输出,可以简单的得出一个结论,不同注册方式的优先级(为了更合理的验证下面的观点,推荐大家修改下上面三个自定义扩展点名,排除掉是因为扩展名导致的排序问题)
配置文件注册 > SPI注册 > 启动时注册
3. 执行顺序指定
对于自定义的扩展点实现,当存在顺序关系时,我们可以通过@Order
注解来实现, 如当上面的三个扩展点都是通过启动方式注册时
@Order(5) public class ApplicationContextInitializer01 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer01"); } } @Order(2) public class ApplicationContextInitializer02 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer02"); } } @Order(10) public class ApplicationContextInitializer03 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer03"); } } @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(Application.class); springApplication.addInitializers(new ApplicationContextInitializer01(), new ApplicationContextInitializer02(), new ApplicationContextInitializer03()); try (ConfigurableApplicationContext context = springApplication.run(args)) { } } }
输出实例如下
接着重点来了
若上面的三个自定义实现,不是相同的注册方式,如将03采用配置文件方式进行注册,那么01, 02 依然是启动注册
则顺序是 03 > 02 > 01
即
@Order
注解修饰的顺序,并不能打破 配置文件 > SPI > 启动方式注册的顺序
关于自定义实现类的执行顺序,规则如下
配置文件 > SPI > 启动方式
相同的注册方式,可以通过
@Order
注解进行修饰,值越小则优先级越高
4. 使用场景示例
最后我们再来看一下,这个扩展点到底有什么用,我们再什么场景下会用到这个呢?
一个经常可以看到的应用场景如通过它来指定需要激活的配置文件
public class ApplicationContextInitializer03 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { // 指定激活prod对应的配置文件 configurableApplicationContext.getEnvironment().setActiveProfiles("prod"); } }
但是一般也很少见到有人这么干,因为直接使用配置参数就行了,那么有场景需要这么做么?
答案当然是有的,比如现在广为流行的docker容器部署,当我们希望每次都是打同一个镜像,然后在实际运行的时候,根据不同的环境来决定当前镜像到底启用哪些配置文件,这时就有用了
比如我们通过容器的环境参数 app.env
来获取当前运行的环境,如果是prod,则激活application-prod.yml
; 如果是test,则激活application-test.yml
application.yml
이 있으며 특별한 구성도 없습니다🎜🎜II. 컨테이너 새로 고침 전 확장 예시 🎜1. Custom ApplicationContextInitializer
🎜를 클릭하세요. 사용자 정의 컨텍스트 초기화를 구현하려면 매우 간단합니다. 🎜public class EenvActiveApplicationContextInitializer implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { String env = System.getenv("app.env"); if ("prod".equalsIgnoreCase(env)) { configurableApplicationContext.getEnvironment().setActiveProfiles("prod"); } else if ("test".equalsIgnoreCase(env)) { configurableApplicationContext.getEnvironment().setActiveProfiles("test"); } else { throw new RuntimeException("非法的环境参数:" + env); } } }
2와 같이 위의 인터페이스를 구현하면 됩니다. . 확장점 등록🎜위의 확장점을 어떻게 사용자 정의하고, 어떻게 적용하나요? 🎜🎜시작 시 직접 등록하는 등 세 가지 방법을 공식적으로 제공합니다. springApplication.addInitializers(new ApplicationContextInitializer01());
🎜rrreee🎜 확장 포인트가 jar 패키지에 배치될 때 외부 서비스를 제공할 때 위의 시작 등록 방법을 사용하는 것은 분명히 불가능합니다. 이때 더 권장되는 방법은 Spring의 SPI 메커니즘🎜🎜META-INF/spring.factories
를 통해 리소스 디렉터리에 등록하는 것입니다. file🎜rrreee🎜지침🎜- 🎜위의 SPI 메커니즘은 이전 기사에서
AutoConfiguration을 사용하는 것이 좋습니다.
는 일반적으로 이런 방식으로 등록됩니다🎜
🎜위의 두 가지 등록 방법 외에도 구성 파일 application.properties
에 구성 파일 방법도 있습니다. > 또는 application.yml
, 다음을 구성합니다. 🎜rrreee🎜테스트 시작🎜🎜위의 세 가지 등록 방법에 대해 세 가지 맞춤형 확장 포인트를 구현하고 시작한 후 실제 출력 살펴보기🎜🎜
🎜🎜위 출력은 다양한 등록 방법의 우선순위라는 결론을 쉽게 도출할 수 있습니다(다음 관점을 보다 합리적으로 확인하려면 위의 세 가지 사용자 정의 확장을 수정하고 제외하는 것이 좋습니다. 이름으로 인한 확장자 정렬 문제)🎜- 🎜구성 파일 등록> 시작 시 등록🎜
3. 시퀀스 사양
🎜사용자 정의 확장 포인트 구현의 경우 시퀀스 관계가 있는 경우 @Order
주석을 통해 구현할 수 있습니다. 예를 들어 위의 세 확장 포인트가 모두 다음을 통해 시작되는 경우입니다. 🎜rrreee🎜등록시 출력 예시는 다음과 같습니다🎜🎜
🎜🎜그러면 핵심이 나옵니다🎜
- 🎜위의 세 가지 사용자 정의 구현이 동일하지 않은 경우 03과 같은 등록 방법 구성 파일 방법을 사용하여 등록하면 01과 02가 계속 등록을 시작합니다🎜
- 🎜순서는 03 > 02 > 🎜즉,
@Order
주석 수정 순서는 구성 파일> 시작 모드 등록🎜
🎜의 순서를 깨뜨릴 수 없습니다. 사용자 정의 구현 클래스의 실행 순서 및 규칙은 다음과 같습니다🎜
- 🎜Configuration file> SPI >up method🎜
- 🎜동일한 등록 방법은 다음과 같습니다. 수정을 위해
@Order code> 주석을 전달합니다. 값이 작을수록 우선순위가 높아집니다🎜
4. 사용 시나리오 예
🎜마지막으로 살펴보겠습니다. 이 확장 포인트의 용도가 무엇인지 살펴보겠습니다. 어떤 시나리오에서 이것을 사용할 것입니까? 🎜🎜일반적으로 볼 수 있는 응용 프로그램 시나리오는 이를 사용하여 활성화해야 하는 구성 파일을 지정하는 것입니다🎜rrreee🎜그러나 일반적으로 구성 매개변수를 직접 사용하는 것으로 충분하므로 이 작업을 수행하는 사람은 거의 없습니다. 이것이 필요한 시나리오는 무엇입니까? 🎜🎜물론 그렇습니다. 예를 들어 현재 널리 사용되는 Docker 컨테이너 배포에서는 매번 동일한 이미지를 빌드하고 실제 작업 중에 현재 이미지에서 활성화할 구성 파일을 결정할 수 있습니다. 다양한 환경에 따라 유용합니다🎜🎜예를 들어, 현재 실행 중인 환경을 얻기 위해 app.env
컨테이너의 환경 매개변수를 사용합니다. prod.yml ; 테스트라면 application-test.yml
을 활성화하세요🎜🎜그럼 지금 하시면 됩니다🎜rrreee
AutoConfiguration을 사용하는 것이 좋습니다.
는 일반적으로 이런 방식으로 등록됩니다🎜@Order
주석 수정 순서는 구성 파일> 시작 모드 등록🎜@Order code> 주석을 전달합니다. 값이 작을수록 우선순위가 높아집니다🎜
위 내용은 SpringBoot 컨테이너가 새로 고쳐지기 전에 ApplicationContextInitializer를 다시 호출하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

신흥 기술은 위협을 일으키고 Java의 플랫폼 독립성을 향상시킵니다. 1) Docker와 같은 클라우드 컴퓨팅 및 컨테이너화 기술은 Java의 플랫폼 독립성을 향상 시키지만 다양한 클라우드 환경에 적응하도록 최적화되어야합니다. 2) WebAssembly는 Graalvm을 통해 Java 코드를 컴파일하여 플랫폼 독립성을 확장하지만 성능을 위해 다른 언어와 경쟁해야합니다.

다른 JVM 구현은 플랫폼 독립성을 제공 할 수 있지만 성능은 약간 다릅니다. 1. OracleHotspot 및 OpenJDKJVM 플랫폼 독립성에서 유사하게 수행되지만 OpenJDK에는 추가 구성이 필요할 수 있습니다. 2. IBMJ9JVM은 특정 운영 체제에서 최적화를 수행합니다. 3. Graalvm은 여러 언어를 지원하며 추가 구성이 필요합니다. 4. AzulzingJVM에는 특정 플랫폼 조정이 필요합니다.

플랫폼 독립성은 여러 운영 체제에서 동일한 코드 세트를 실행하여 개발 비용을 줄이고 개발 시간을 단축시킵니다. 구체적으로, 그것은 다음과 같이 나타납니다. 1. 개발 시간을 줄이면 하나의 코드 세트 만 필요합니다. 2. 유지 보수 비용을 줄이고 테스트 프로세스를 통합합니다. 3. 배포 프로세스를 단순화하기위한 빠른 반복 및 팀 협업.

Java'SplatformIndenceFacilitatesCodereScoderEByWatHeAveringByTeCodetOrunonAnyPlatformwitHajvm.1) DevelopersCanwriteCodeOnceforConsentEStentBehaviorAcRossPlatforms.2) MAINTENDUCEDSCODEDOES.3) LIBRRIESASHSCORAREDERSCRAPERAREDERSPROJ

Java 응용 프로그램의 플랫폼 별 문제를 해결하려면 다음 단계를 수행 할 수 있습니다. 1. Java의 시스템 클래스를 사용하여 시스템 속성을보고 실행중인 환경을 이해합니다. 2. 파일 클래스 또는 java.nio.file 패키지를 사용하여 파일 경로를 처리하십시오. 3. 운영 체제 조건에 따라 로컬 라이브러리를로드하십시오. 4. visualVM 또는 JProfiler를 사용하여 크로스 플랫폼 성능을 최적화하십시오. 5. 테스트 환경이 Docker Containerization을 통해 생산 환경과 일치하는지 확인하십시오. 6. githubactions를 사용하여 여러 플랫폼에서 자동 테스트를 수행하십시오. 이러한 방법은 Java 응용 프로그램에서 플랫폼 별 문제를 효과적으로 해결하는 데 도움이됩니다.

클래스 로더는 통합 클래스 파일 형식, 동적로드, 부모 위임 모델 및 플랫폼 독립적 인 바이트 코드를 통해 다른 플랫폼에서 Java 프로그램의 일관성과 호환성을 보장하고 플랫폼 독립성을 달성합니다.

Java 컴파일러가 생성 한 코드는 플랫폼 독립적이지만 궁극적으로 실행되는 코드는 플랫폼 별입니다. 1. Java 소스 코드는 플랫폼 독립적 인 바이트 코드로 컴파일됩니다. 2. JVM은 바이트 코드를 특정 플랫폼의 기계 코드로 변환하여 크로스 플랫폼 작동을 보장하지만 성능이 다를 수 있습니다.

멀티 스레딩은 프로그램 대응 성과 리소스 활용을 향상시키고 복잡한 동시 작업을 처리 할 수 있기 때문에 현대 프로그래밍에서 중요합니다. JVM은 스레드 매핑, 스케줄링 메커니즘 및 동기화 잠금 메커니즘을 통해 다양한 운영 체제에서 멀티 스레드의 일관성과 효율성을 보장합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

VSCode Windows 64비트 다운로드
Microsoft에서 출시한 강력한 무료 IDE 편집기

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.
