• 010-Spring Boot 扩展分析-ApplicationContextInitializer、CommandLineRunner、ApplicationRunner


    一、常见的两个扩展点

    1、ApplicationContextInitializer

    1.1、作用实现

    作用:接口实在Spring容器执行refresh之前的一个回调。

    Callback interface for initializing a Spring {@link ConfigurableApplicationContext}

    实现:

    /*
     * Copyright 2002-2011 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.context;
    
    /**
     * Callback interface for initializing a Spring {@link ConfigurableApplicationContext}
     * prior to being {@linkplain ConfigurableApplicationContext#refresh() refreshed}.
     *
     * <p>Typically used within web applications that require some programmatic initialization
     * of the application context. For example, registering property sources or activating
     * profiles against the {@linkplain ConfigurableApplicationContext#getEnvironment()
     * context's environment}. See {@code ContextLoader} and {@code FrameworkServlet} support
     * for declaring a "contextInitializerClasses" context-param and init-param, respectively.
     *
     * <p>{@code ApplicationContextInitializer} processors are encouraged to detect
     * whether Spring's {@link org.springframework.core.Ordered Ordered} interface has been
     * implemented or if the @{@link org.springframework.core.annotation.Order Order}
     * annotation is present and to sort instances accordingly if so prior to invocation.
     *
     * @author Chris Beams
     * @since 3.1
     * @see org.springframework.web.context.ContextLoader#customizeContext
     * @see org.springframework.web.context.ContextLoader#CONTEXT_INITIALIZER_CLASSES_PARAM
     * @see org.springframework.web.servlet.FrameworkServlet#setContextInitializerClasses
     * @see org.springframework.web.servlet.FrameworkServlet#applyInitializers
     */
    public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
    
        /**
         * Initialize the given application context.
         * @param applicationContext the application to configure
         */
        void initialize(C applicationContext);
    
    }
    View Code

    1.2、使用步骤

    步骤一、写一个类,实现ApplicationContextInitializer接口

    步骤二、注册ApplicationContextInitializer接口的实现

    注册方式

    方式一、SpringApplication 

            SpringApplication application = new SpringApplication(App.class);
            application.addInitializers(new MyApplicationContextInitializer());

    方式二、配置文件

    context.initializer.classes=com.lhx.spring.springboot_enableauto.MyApplicationContextInitializer

    多个用逗号隔开

    方式三、使用spring.factories配置机制,注册监听器

    在需要注入的项目包中添加META-INF/spring.factories

    org.springframework.context.ApplicationContextInitializer=类名

    1.3、使用:

    新建一个:MyApplicationContextInitializer

    package com.lhx.spring.springboot_enableauto;
    
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    
    public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    
        @Override
        public void initialize(ConfigurableApplicationContext applicationContext) {
            System.out.println("bean count:" + applicationContext.getBeanDefinitionCount());
            // ConfigurableListableBeanFactory factory =
            // applicationContext.getBeanFactory();
        }
    
    }
    View Code

    调用

    package com.lhx.spring.springboot_enableauto;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    public class App {
        public static void main(String[] args) {
            // ConfigurableApplicationContext context = SpringApplication.run(App.class,
            // args);
            SpringApplication application = new SpringApplication(App.class);
            application.addInitializers(new MyApplicationContextInitializer());
            ConfigurableApplicationContext context = application.run(args);
    
            context.close();
        }
    }
    View Code

    2、CommandLineRunner、ApplicationRunner【类似开机自启动】

    2.1、作用于实现

    作用:在spring容器全部初始化完毕,接口在容器启动成功后的最后一步回调

    * Interface used to indicate that a bean should <em>run</em> when it is contained within
    * a {@link SpringApplication}. Multiple {@link CommandLineRunner} beans can be defined
    * within the same application context and can be ordered using the {@link Ordered}
    * interface or {@link Order @Order} annotation.

    实现

    /*
     * Copyright 2012-2015 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.boot;
    
    import org.springframework.core.Ordered;
    import org.springframework.core.annotation.Order;
    
    /**
     * Interface used to indicate that a bean should <em>run</em> when it is contained within
     * a {@link SpringApplication}. Multiple {@link CommandLineRunner} beans can be defined
     * within the same application context and can be ordered using the {@link Ordered}
     * interface or {@link Order @Order} annotation.
     * <p>
     * If you need access to {@link ApplicationArguments} instead of the raw String array
     * consider using {@link ApplicationRunner}.
     *
     * @author Dave Syer
     * @see ApplicationRunner
     */
    public interface CommandLineRunner {
    
        /**
         * Callback used to run the bean.
         * @param args incoming main method arguments
         * @throws Exception on error
         */
        void run(String... args) throws Exception;
    
    }
    View Code

    2.2、使用步骤

    步骤一、写一个类实现CommandLineRunner接口

    步骤二、把该类加入到Spring容器之中,可以通过@Order或Ordered接口控制顺序,注解越小越先执行

    2.3、使用

    新建一个类ServerSuccessReport实现接口CommandLineRunner

    package com.lhx.spring.springboot_enableauto;
    
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ServerSuccessReport implements CommandLineRunner {
    
        @Override
        public void run(String... args) throws Exception {
            System.out.println("----CommandLineRunner执行-----");
        }
    
    }
    View Code

    注意同类接口

    ApplicationRunner,

    void run(ApplicationArguments args) 

    只是参数不一样

    CommandLineRunner是原始参数,没有任何处理

    ApplicationRunner是ApplicationArguments 对象,是对原始参数进一步的封装

    3.ApplicationArguments 

    是对参数(main方法)进一步重载

    可以解析--name=value的,可以通过name获取value

    package com.lhx.spring.springboot_enableauto;
    
    import org.springframework.boot.ApplicationArguments;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    public class App {
        public static void main(String[] args) {
            SpringApplication application = new SpringApplication(App.class);
            ConfigurableApplicationContext context = application.run(args);
    
            ApplicationArguments arguments = context.getBean(ApplicationArguments.class);
            System.out.println(arguments.getSourceArgs().length);
            System.out.println(arguments.getOptionNames());
            System.out.println(arguments.getOptionValues("name"));
    
            context.close();
        }
    }
  • 相关阅读:
    P2149 [SDOI2009]Elaxia的路线
    P1346 电车
    P3174 [HAOI2009]毛毛虫
    P3047 [USACO12FEB]附近的牛Nearby Cows
    P4053 [JSOI2007]建筑抢修
    P2607 [ZJOI2008]骑士
    [HNOI2006]马步距离
    [POI2014]Hotel
    [BZOJ3856]Monster
    [BZOJ2819]Nim
  • 原文地址:https://www.cnblogs.com/bjlhx/p/8353362.html
Copyright © 2020-2023  润新知