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();
    }
}

 

posted @ 2018-01-25 22:06  bjlhx15  阅读(521)  评论(0编辑  收藏  举报
Copyright ©2011~2020 JD-李宏旭