当前位置: 首页> 汽车> 报价 > 微信小程序店铺开通要多少钱_e福州电子公交卡_福建百度代理公司_长沙百度公司

微信小程序店铺开通要多少钱_e福州电子公交卡_福建百度代理公司_长沙百度公司

时间:2025/7/11 14:52:42来源:https://blog.csdn.net/m0_57801749/article/details/142643295 浏览次数: 0次
微信小程序店铺开通要多少钱_e福州电子公交卡_福建百度代理公司_长沙百度公司

1.自定义条件注解

1.1 @conditional注解

@Conditional注解是Spring框架中的一个条件注解,可以根据不同的条件来决定是否需要创建一个Bean对象。其工作原理是,在Bean创建之前根据条件判断进行筛选,只有当条件满足时才会创建Bean对象。

1.2自定义条件注解

(1)实现Condition接口

public class RedisCustomCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Environment environment = context.getEnvironment();String property = environment.getProperty("redis.configuration.off");if (Strings.isBlank(property)){return false;}return property.equalsIgnoreCase("true");}
}

(2)自定义注解,这样当我们在@Configuration类上使用@CustomConditionAnnotation注解时,框架会判断CustomCondition类的matches()方法是否返回true,如果是,则创建这个Bean对象。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.ANNOTATION_TYPE})
@Conditional(value = RedisCustomCondition.class)
public @interface RedisCustomConditionAnnotation {
}

(3)在条件装配的场景使用该注解

@Configuration
@RedisCustomConditionAnnotation
public class RedisConfig {....
}

(4)配置

redis.configuration.off = false

应用:可以用作某个配置是否交给spring管理的开关

2. ApplicationContextInitializer

2.1作用

通常用于需要在应用程序上下文中进行一些程序化初始化的 Web 应用程序。例如,注册属性源或激活与上下文环境相关的配置文件。

2.2 加载和初始化时机

通过实现ApplicationContextInitializer接口,可以在ApplicationContext创建之前对其进行一些定制化的修改

源码使用位置

org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class<T>)

来获取 META-INF/spring.factories 中配置 key 为 org.springframework.context.ApplicationContextInitializer 的数据

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

ApplicationContextInitializer 的初始化时机

查看 SpringApplicationrun(String... args) 方法,如下所示:

	public ConfigurableApplicationContext run(String... args) {//监控器监听容器启动并进行图形化页面处理Startup startup = Startup.create();if (this.registerShutdownHook) {SpringApplication.shutdownHook.enableShutdownHookAddition();}//创建默认的引导上下文DefaultBootstrapContext bootstrapContext = createBootstrapContext();ConfigurableApplicationContext context = null;//图形化页面开启configureHeadlessProperty();//添加监听器SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting(bootstrapContext, this.mainApplicationClass);try {//加载参数ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//环境准备ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);//banner打印Banner printedBanner = printBanner(environment);//创建Spring应用上下文context = createApplicationContext();//设置引导器context.setApplicationStartup(this.applicationStartup);/*** 准备上下文: 期间就会调用ApplicationContextInitializer */prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);//刷新上下文(包括单实例创建,前置处理和后置处理器,代理对象创建(aop)等一系列过程)refreshContext(context);//Spring应用上下文收尾阶段afterRefresh(context, applicationArguments);startup.started();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), startup);}listeners.started(context, startup.timeTakenToStarted());//回调工作处理: 处理实现了ApplicationRunner 或 CommandLineRunner 接口的类,做一些容器启动成功后的预处理工作callRunners(context, applicationArguments);}catch (Throwable ex) {throw handleRunFailure(context, ex, listeners);}try {if (context.isRunning()) {listeners.ready(context, startup.ready());}}catch (Throwable ex) {throw handleRunFailure(context, ex, null);}return context;}

进入上述 prepareContext 方法,可以看到applyInitializers(context)方法

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {context.setEnvironment(environment);postProcessApplicationContext(context);addAotGeneratedInitializerIfNecessary(this.initializers);applyInitializers(context);listeners.contextPrepared(context);bootstrapContext.close(context);
}

进入上述 applyInitializers(context) 方法,可以看到这里循环处理实现了ApplicationContextInitializer接口的类

	protected void applyInitializers(ConfigurableApplicationContext context) {for (ApplicationContextInitializer initializer : getInitializers()) {Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),ApplicationContextInitializer.class);Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");initializer.initialize(context);}}
2.3 应用:
  1. 修改Spring Boot默认的environment属性。使用configurableApplicationContext.getEnvironment()方法获取到environment对象,从而修改环境变量,例如添加自定义配置文件路径。

  2. 添加自定义的PropertySource。使用environment.getPropertySources().addLast(propertySource)方法,可以添加自定义的属性源,从而实现更灵活的配置。

  3. 注册自定义bean。使用configurableApplicationContext.getBeanFactory().registerSingleton(beanName, bean)方法,可以注册自定义的bean,从而实现更灵活的依赖注入。

举例:

(1)添加自定义配置文件

/*** 修改Spring Boot默认的environment属性。* 使用configurableApplicationContext.getEnvironment()方法获取到environment对象,从而修改环境变量,例如添加自定义配置文件路径。**/
public class InterveneApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {ConfigurableEnvironment environment = applicationContext.getEnvironment();// 添加自定义配置文件路径try {System.out.println("InterveneApplicationContextInitializer initialize :" + environment);environment.getPropertySources().addFirst(new ResourcePropertySource("classpath:liugp.properties"));System.out.println("InterveneApplicationContextInitializer initialize add FirstResourcePropertySource  classpath:zyftest.properties");} catch (IOException e) {e.printStackTrace();}}
}

上述代码中的InterveneApplicationContextInitializer需要被注册才能生效。可以通过在src/main/resources/META-INF/spring.factories文件中指定注册项的方式来注册:

org.springframework.context.ApplicationContextInitializer=\
com.example.demo17.config.hbase.InterveneApplicationContextInitializer

(2)添加自定义的属性源,从而实现更灵活的配置

/*** 添加自定义的PropertySource。* 使用environment.getPropertySources().addLast(propertySource)方法,可以添加自定义的属性源,从而实现更灵活的配置。*/
public class InterveneApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext configurableApplicationContext) {// 添加自定义的PropertySourcePropertySource<?> propertySource = new MyPropertySource("myPropertySource");ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();environment.getPropertySources().addLast(propertySource);System.out.println("InterveneApplicationContextInitializer initialize add PropertySource  myPropertySource");}// 自定义PropertySourceprivate static class MyPropertySource extends PropertySource<String> {private static final String MY_PROPERTY_SOURCE_KEY = "my.property.source.key";public MyPropertySource(String name) {super(name);}@Overridepublic Object getProperty(String name) {if (MY_PROPERTY_SOURCE_KEY.equals(name)) {return "myPropertySourceValue";}return null;}}
}

这样就可以通过@Value("${my.property.source.key}")的方式在应用程序中获取到它的值了;

同上:上述代码中的InterveneApplicationContextInitializer需要被注册才能生效

(3)注册自定义bean

/*** 注册自定义bean。* 使用configurableApplicationContext.getBeanFactory().registerSingleton(beanName, bean)方法,可以注册自定义的bean,从而实现更灵活的依赖注入。*/
public class InterveneApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext configurableApplicationContext) {ConfigurableListableBeanFactory beanFactory = configurableApplicationContext.getBeanFactory();// 注册自定义BeanMyBean myBean = new MyBean();beanFactory.registerSingleton("myBean", myBean);System.out.println("InterveneApplicationContextInitializer initialize registerSingleton  myBean");}}

同上:上述代码中的InterveneApplicationContextInitializer需要被注册才能生效

3. ApplicationRunner 接口

应用:在Spring容器启动期间,容器刷新完成后做一些初始化操作(比如:预加载一些元数据,环境预热等)

用法:实现ApplicationRunner接口,交给Spring管理

/*** 项目启动时执行,预先加载初始化数据* */
@Component
public class ApplicationRunnerTest implements ApplicationRunner {@Overridepublic void run(String... args) throws Exception {new Thread(()->{System.out.println("Hello ApplicationRunner!");}).start();}
}

4. CommandLineRunner 接口

用法作用和ApplicationRunner 类似

/*** 项目启动时执行,预先加载命令行相关数据* */
@Component
public class CommandLineRunnerTest implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {new Thread(()->{System.out.println("Hello CommandLineRunner!");}).start();}
}

5. SpringApplicationRunListener

SpringApplicationRunListener是Spring Boot的一个事件监听器,用于在应用程序启动和停止时执行一些操作。

/*** SpringApplicationRunListener是Spring Boot的一个事件监听器,用于在应用程序启动和停止时执行一些操作。* 可能需要自定义SpringApplicationRunListener来执行某些特定操作。* 下面是一个示例,演示如何扩展SpringApplicationRunListener以添加自定义操作* */
public class InterveneRunListener implements SpringApplicationRunListener {private final SpringApplication application;private final String[] args;public InterveneRunListener(SpringApplication application, String[] args) {this.application = application;this.args = args;}@Overridepublic void starting(ConfigurableBootstrapContext bootstrapContext) {System.out.println("SpringApplicationRunListener ... starting ");SpringApplicationRunListener.super.starting(bootstrapContext);}@Overridepublic void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {System.out.println("SpringApplicationRunListener ... environmentPrepared ");SpringApplicationRunListener.super.environmentPrepared(bootstrapContext, environment);}@Overridepublic void contextPrepared(ConfigurableApplicationContext context) {System.out.println("SpringApplicationRunListener ... contextPrepared ");SpringApplicationRunListener.super.contextPrepared(context);}@Overridepublic void contextLoaded(ConfigurableApplicationContext context) {System.out.println("SpringApplicationRunListener ... contextLoaded ");SpringApplicationRunListener.super.contextLoaded(context);}@Overridepublic void started(ConfigurableApplicationContext context, Duration timeTaken) {System.out.println("SpringApplicationRunListener ... started ");SpringApplicationRunListener.super.started(context, timeTaken);}@Overridepublic void ready(ConfigurableApplicationContext context, Duration timeTaken) {System.out.println("SpringApplicationRunListener ... ready ");SpringApplicationRunListener.super.ready(context, timeTaken);}@Overridepublic void failed(ConfigurableApplicationContext context, Throwable exception) {System.out.println("SpringApplicationRunListener ... failed ");SpringApplicationRunListener.super.failed(context, exception);}
}

上述代码中的InterveneRunListener需要被注册才能生效。可以通过在src/main/resources/META-INF/spring.factories文件中指定注册项的方式来注册:

org.springframework.boot.SpringApplicationRunListener=\
com.example.demo17.config.hbase.InterveneRunListener

6. BeanFactoryAware

使用场景:可以在bean实例化之后,但还未初始化之前,拿到 BeanFactory,在这个时候,可以对每个bean进行特殊化的定制。也或者可以把BeanFactory拿到进行缓存,日后使用。

  • 获取其他 bean 实例:通过 BeanFactory 引用,这个 bean 可以动态地获取容器中的其他 bean 实例。

  • 访问容器的配置信息:通过 BeanFactory,这个 bean 可以访问容器的配置信息,例如属性文件、环境变量等。

  • 控制 bean 的生命周期:通过 BeanFactory,这个 bean 可以在需要时自定义自己的初始化逻辑,或者在销毁时执行一些清理操作。

注册Bean

@Component
public class ApplicationListenerTest implements BeanFactoryAware {private ConfigurableListableBeanFactory configurableListableBeanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {configurableListableBeanFactory = (ConfigurableListableBeanFactory) beanFactory;configurableListableBeanFactory.registerSingleton("object",new Object());}
}

7. ApplicationContextAware

7.1应用场景

ApplicationContextAware可以用于各种场景,其中一些常见的包括:

访问其他Bean: 可以通过ApplicationContextAware获取其他Bean的实例,以便在Bean中调用其他Bean的方法或访问其他Bean的属性。 执行特定逻辑: 可以在获取到Spring容器上下文后执行特定的逻辑,例如执行一些初始化任务或后处理任务。 获取Spring容器信息: 可以获取Spring容器的各种信息,例如Bean的定义、环境属性、配置信息等。

@Component
public class ApplicationListenerTest implements ApplicationContextAware {@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {//通过注解获取beanMap<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(CustomConditionAnnotation.class);//通过接口获取beanMap<String, Condition> beansOfType = applicationContext.getBeansOfType(Condition.class);}
}

8. InitializingBean 和 @PostConstruct

主要适用于处理非静态成员的初始化,所以这个接口的用途就是用来实现初始化数据用的。

比如某些init操作

public class RetryTemplateTest {private RetryTemplate retryTemplate;static Long RETRY_TIME = 1000L;@PostConstructpublic void init() {rateLimiter = RateLimiter.create(Double.parseDouble(globalArkConfig.getRateLimiterRate()));this.retryTemplate = createRetryTemplate();}/*** 定义重试策略:可以定义重试的次数、每次重试之间的间隔时间,甚至可以设置不同的重试策略(如指数退避策略)*/private static RetryTemplate createRetryTemplate() {RetryTemplate retryTemplate = new RetryTemplate();// 设置重试策略,无线重试AlwaysRetryPolicy alwaysRetryPolicy = new AlwaysRetryPolicy();retryTemplate.setRetryPolicy(alwaysRetryPolicy);//设置重试策略,最高重试100次SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();simpleRetryPolicy.setMaxAttempts(5);retryTemplate.setRetryPolicy(simpleRetryPolicy);// 设置回退策略-重试的间隔策略FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();//重试间隔msbackOffPolicy.setBackOffPeriod(1000);retryTemplate.setBackOffPolicy(backOffPolicy);//设置监听器RetryListener retryListener = new RetryListener() {@Overridepublic <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {System.out.println("---open----在第一次重试时调用");return true;}@Overridepublic <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {System.out.println("close----在最后一次重试后调用(无论成功与失败)。" + context.getRetryCount());}@Overridepublic <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {System.out.println("error----在每次调用异常时调用。" + context.getRetryCount());}};retryTemplate.registerListener(retryListener);return retryTemplate;}public static void main(String[] args) {ForkJoinPool forkJoinPool = new ForkJoinPool(16);try {ArrayList<Integer> list = new ArrayList<>(1000);for (int i = 0; i < 101; i++) {list.add(i);}System.out.println("数据准备完成。" + Thread.currentThread().getName());forkJoinPool.submit(() -> {list.parallelStream().forEach(res -> {/*** 通过 RetryTemplate 的 execute 方法来执行需要重试的操作。如果操作成功,则返回结果;* 如果失败,则根据定义的重试策略进行重试。*/retryTemplate.execute(//每次重试的操作retryContext -> {if (res == 100) {throw new RuntimeException("偶数异常 => " + res);}return 0;},//达到最大重试次数后执行,并以其返回结果作为最终的返回结果retryContext -> {throw new RuntimeException("达到最大重试次数后 => " + res);});});}).get();} catch (Exception e) {throw new RuntimeException("捕获到线程内部异常 => " + e);} finally {forkJoinPool.shutdown();}}
}

9. InstantiationAwareBeanPostProcessor

  • InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所以实现这个接口需要实现5个方法。InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置

  • postProcessBeforeInstantiation方法是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走

  • postProcessAfterInstantiation方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true, postProcessPropertyValues就会被执行

  • postProcessPropertyValues方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改

  • 父接口BeanPostProcessor的2个方法postProcessBeforeInitialization和postProcessAfterInitialization都是在目标对象被实例化之后,并且属性也被设置之后调用的

10. BeanPostProcessor

BeanProcessor主要应用在以下几个方面:

  • 依赖注入的简化: 通过BeanPostProcessor,我们可以轻松实现依赖注入,减少了手动管理对象之间的依赖关系的复杂性,提高了代码的可测试性和可维护性。

  • 面向切面编程(AOP)的支持: BeanPostProcessor提供了AOP的支持,使得我们可以更加灵活地实现横切关注点,如日志记录、事务管理等,将这些与核心业务逻辑分离开来,提高了代码的模块化程度。

  • 配置管理的优化: 通过BeanPostProcessor,我们可以将配置信息与代码分离,实现了配置的集中管理和动态加载,降低了系统的耦合度,使得系统更易于维护和扩展。

执行顺序

ApplicationContextInitializer>静态代码块 > 构造方法 > BeanFactoryAware > ApplicationContextAware > @PostConstruct > InitializingBean > InstantiationAwareBeanPostProcessor > BeanPostProcessor > ApplicationRunner

11. Spring Boot 程序的启动时间优化

  • 减少依赖项:评估项目的依赖项,并确保只引入必要的依赖。较多的依赖项可能会增加启动时间,因为它们需要被扫描和初始化。通过删除不需要的依赖项或仅引入必要的模块,可以减少类路径的扫描和初始化时间。

  • 调整自动配置:Spring Boot 的自动配置是一个强大的特性,但有时可能会引入不必要的组件和功能。通过调整自动配置,可以精确地指定所需的配置,避免加载不必要的组件,从而减少启动时间。

  • 启用懒加载:将一些不常用的组件设置为懒加载,即在需要时才进行初始化。通过懒加载,可以避免在启动阶段初始化不必要的组件,从而加快启动时间。可以使用 Spring Framework 的 @Lazy 注解或在配置类中进行相应的配置。

    使用 @Lazy 注解:在需要懒加载的组件上使用 Spring Framework 的 @Lazy 注解。将 @Lazy 注解应用于组件的声明处,以指示该组件应该在需要时才进行初始化。

    @Component
    @Lazy
    public class MyLazyComponent {// ...
    }

    在配置类中进行配置:如果你使用的是配置类来进行组件的配置,你可以在配置类的方法上使用 @Lazy 注解,将需要懒加载的组件进行标记

    @Configuration
    public class MyConfig {@Bean@Lazypublic MyLazyComponent myLazyComponent() {return new MyLazyComponent();}
    }

  • 启用编译时优化:使用 Spring Boot 2.4 及更高版本,你可以通过启用编译时优化来加快启动时间。通过在 pom.xml 文件中设置 <compilerArgs> 属性,使用 --add-opens 选项来启用编译时优化。这可以减少反射操作的开销,从而提高启动性能。

    确认使用的 Spring Boot 版本:确保你的项目使用的是 Spring Boot 2.4 或更高版本。编译时优化功能是在 Spring Boot 2.4 中引入的。 配置 pom.xml 文件:在项目的 pom.xml 文件中,找到 <build> 元素,并在其中的 <plugins> 元素下添加 Maven Compiler 插件配置。在 Maven Compiler 插件配置中,使用 <compilerArgs> 属性来设置编译器选项。

    <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><compilerArgs><arg>--add-opens</arg><arg>java.base/java.lang=ALL-UNNAMED</arg><arg>--add-opens</arg><arg>java.base/java.util=ALL-UNNAMED</arg><!-- 添加其他需要的 --add-opens 选项 --></compilerArgs></configuration></plugin></plugins>
    </build>

    <compilerArgs> 属性中,我们使用 --add-opens 选项来指定需要开放的包和模块。上述示例中,我们设置了两个 --add-opens 选项,分别是 java.lang 和 java.util 包。你还可以根据需要添加其他的 --add-opens 选项,以开放其他需要的包和模块。 重新构建应用程序:保存更改后,重新构建应用程序。在编译过程中,编译器将使用指定的编译器选项,启用编译时优化功能。

  • 调整日志级别:Spring Boot 默认启用了相对较高的日志级别,这可能会导致大量的日志输出,从而增加启动时间。通过将日志级别调整为更低的级别,如将 INFO 调整为 WARN,可以减少日志输出,从而缩短启动时间。

  • 使用缓存:Spring Boot 在启动过程中会进行多个步骤的扫描和初始化。通过使用缓存机制,可以缓存一些元数据和初始化结果,避免重复的扫描和初始化操作,从而提高启动性能。可以使用 Spring Boot 的缓存机制或其他缓存库来实现。

参考原文链接:

分析SpringBoot启动配置原理_spring启动加载顺序及原理-CSDN博客

关键字:微信小程序店铺开通要多少钱_e福州电子公交卡_福建百度代理公司_长沙百度公司

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: