SpringBoot 2.0 系列005 --啓動實戰之SpringApplication應用

SpringBoot 2.0 系列005 --啓動實戰之SpringApplication應用

注意是隻使用了@EnableAutoConfiguration,默認是隻掃描這一個咱們自定義的類到bean中。不含子包和本包。下一篇咱們分析緣由。git

package hello;

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@Controller
@EnableAutoConfiguration
public class SampleController {

    @RequestMapping("/")
    @ResponseBody
    String home() {
        return "Hello World!";
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(SampleController.class, args);
    }
}
  • 拆分步驟

在以前的文章中咱們提到,SB啓動分爲兩步,new SpringApplication對象和執行run方法。web

// 第一步
        SpringApplication application = new SpringApplication(SpringBootApplication05.class);
        // 第二步 
        ConfigurableApplicationContext context = application.run(args);

第一步

建立對象後 返回SpringApplication對象,咱們來分析此對象有用的幾個方法。spring

構造方法

實例化SpringApplication對象springboot

public SpringApplication(Class<?>... primarySources) {
		this(null, primarySources);
	}

經過構造方法 咱們發現是能夠傳遞多個class對象,即除了傳遞啓動類之外,咱們也能夠傳遞其餘Class對象 能夠是@configuration註解包含的對象 固然也能夠是其餘註解類型的。app

  • 示例

咱們能夠將UserService.class交給SpringBoot進行管理ide

SpringApplication application2=new SpringApplication(SpringBootApplication05_01.class,UserService.class);

addPrimarySources 方法

此種方式等價於構造方法方式。可實現多個class注入。spring-boot

Set primarySources = new LinkedHashSet<>(Arrays.asList(SpringBootApplication05_01.class,UserService.class));
            application.addPrimarySources(primarySources);

setAdditionalProfiles

設置附加的Profiles,我的理解等價於Spring.profiles.active,使用方式以下post

//默認執行application-dev.yml文件中的配置
  application.setAdditionalProfiles("dev");

setBannerMode

設置Banner工做模式 可關閉,也能夠在控制檯和log中,使用方式以下ui

application.setBannerMode(Banner.Mode.CONSOLE);// 控制檯輸出
application.setBannerMode(Banner.Mode.OFF);// 關閉輸出

setBanner

設置banner樣式,也能夠經過spring.banner.location=https://gitee.com/bgt0314/mix_learn/raw/master/SpringBootDemo/src/main/resources/my.txt 來配置。this

application.setBanner(new Banner() {
                @Override
                public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
                    out.println("////////////////////////////////////////////////////////////////////\n" +
                            "//                          _ooOoo_                               //\n" +
                            "//                         o8888888o                              //\n" +
                            "//                         88\" . \"88                              //\n" +
                            "//                         (| ^_^ |)                              //\n" +
                            "//                         O\\  =  /O                              //\n" +
                            "//                      ____/`---'\\____                           //\n" +
                            "//                    .'  \\\\|     |//  `.                         //\n" +
                            "//                   /  \\\\|||  :  |||//  \\                        //\n" +
                            "//                  /  _||||| -:- |||||-  \\                       //\n" +
                            "//                  |   | \\\\\\  -  /// |   |                       //\n" +
                            "//                  | \\_|  ''\\---/''  |   |                       //\n" +
                            "//                  \\  .-\\__  `-`  ___/-. /                       //\n" +
                            "//                ___`. .'  /--.--\\  `. . ___                     //\n" +
                            "//              .\"\" '<  `.___\\_<|>_/___.'  >'\"\".                  //\n" +
                            "//            | | :  `- \\`.;`\\ _ /`;.`/ - ` : | |                 //\n" +
                            "//            \\  \\ `-.   \\_ __\\ /__ _/   .-` /  /                 //\n" +
                            "//      ========`-.____`-.___\\_____/___.-`____.-'========         //\n" +
                            "//                           `=---='                              //\n" +
                            "//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //\n" +
                            "//         佛祖保佑       永無BUG     永不修改                    //\n" +
                            "//                                                    ricky製做   //\n" +
                            "////////////////////////////////////////////////////////////////////");
                }
            });

設置完畢後,springbootbanner變成上述的形式。

setLogStartupInfo

設置啓動日誌,默認true

/**
 *
 true的時候會多出下面兩行日誌  關閉後不打印這兩行
 2018-05-17 10:24:50.585  INFO 20536 --- [           main] com.ricky01.SpringBootApplication05_01   : The following profiles are active: dev
 2018-05-17 10:24:50.697  INFO 20536 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@cd3fee8: startup date [Thu May 17 10:24:50 CST 2018]; root of context hierarchy

 */
application.setLogStartupInfo(false);

addInitializers

添加ApplicationContextInitializer類型的實例,在ConfigurableApplicationContext刷新以前初始化Spring ConfigurableApplicationContext的回調接口

application.addInitializers(new ApplicationContextInitializer<GenericApplicationContext>() {
                @Override
                public void initialize(GenericApplicationContext ctx) {
                    // 能夠根據上下文提早設置一些參數
                    ctx.registerBean("rickyDefault",User.class,User::new); // 注入默認UserBean對象
                    ConfigurableListableBeanFactory beanFactory = ctx.getBeanFactory();
                    System.out.println(ctx.getBeanDefinitionCount());
                    ConfigurableEnvironment environment = ctx.getEnvironment();
                    System.out.println("ApplicationContextInitializer::::::::::"+environment.getPropertySources());

                }
            });

addListeners

添加監聽事件

// 能夠監聽 ApplicationEvent的子類的事件  好比context刷新和關閉等等
            // 在application.properties中配置context.listener.classes=xxx 或者
            /**
             *
             @Component
            public class XXClass{
                @EventListener
                public void onApplicationEvent(ContextRefreshedEvent event) {
                System.out.println("哎喲 等價 我監聽到了呢");
                }
            }
             */

            // 跟setListeners相似

        ApplicationListener<ContextRefreshedEvent> applicationListener = new ApplicationListener<ContextRefreshedEvent>() {

            @Override
            public void onApplicationEvent(ContextRefreshedEvent event) {
                System.out.println("哎喲,我是這個時候刷新完了:" + event.getTimestamp() + ",刷新後你要幹啥呢?");
            }
        };
        application.addListeners(applicationListener);

第二步

run後咱們能夠操做的方法。

// 默認是以下  固然也能夠轉換成其餘context好比logstart裏面打印的AnnotationConfigServletWebServerApplicationContext
 ConfigurableApplicationContext context = application.run(args);
  • 前提,咱們在啓動類中注入以下對象
@Bean
    public User createUser(){
        return new User("ricky",10);
    }
    @Bean
    @Primary // 當使用類獲取bean實例的時候使用
    public User createUser2(){
        return new User("ricky02",10);
    }

    @Bean("rickyUser") // 指定bean的名稱
    public User createUser3(){
        return new User("ricky03",10);
    }
  • context.getBeansOfType

根據class獲取bean對象,是個集合

// 獲取全部的User的bean實例
System.out.println(context.getBeansOfType(User.class));
  • context.getBean(String beanName)

根據BeanName獲取bean對象,是單個對象

// 獲取beanName是createUser的bean對象
            System.out.println("createUser-----------------"+context.getBean("createUser"));
  • context.getBean(Class requiredType)

根據class獲取bean對象,是單個對象,當有多個是須要使用@Primary

User defaultUser = context.getBean(User.class);
// 此例子是獲取到的createUser2對象
            System.out.println("User.class-----------------"+defaultUser);
  • context.getBeanDefinitionNames()

獲取已經裝載的bean對象

String[] BeanDefinitionNames = context.getBeanDefinitionNames();
            System.out.print("包含的bean對象:");
           for (String name:BeanDefinitionNames){
               System.out.println(name+",");
           }
  • context.getApplicationName()

獲取應用名稱

String applicationName = context.getApplicationName();
            System.out.println("applicationName:"+applicationName);
  • context.getBeanDefinitionCount()

獲取bean數量

int beannum=context.getBeanDefinitionCount();
            System.out.println("bean的數量:"+beannum);
  • context.publishEvent

發佈ApplicationEvent 自定義的事件須要在此處發佈

// 發佈自定義事件
            context.publishEvent(new MyApplicationEvent(new Object()));
  • context.addApplicationListener

添加監聽

// 等同上述 applicationListener
             context.addApplicationListener(applicationListener);
  • context.addBeanFactoryPostProcessor

添加BeanFactoryPostProcessor,可是此處無效,

// bean工廠加載完畢的後置通知  可是在這裏無效  實現方式參照 createBeanDefinitionRegistryPost()方法
            context.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
                @Override
                public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                    System.out.println("--------------------------------"+beanFactory.getBeanDefinitionCount());
                }
            });

有效實現方式以下

@Bean
    public  BeanDefinitionRegistryPostProcessor createBeanDefinitionRegistryPost(){
        return new BeanDefinitionRegistryPostProcessor() {
            @Override
            public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//                    BeanDefinitionBuilder builder=BeanDefinitionBuilder.rootBeanDefinition(User.class);
//                    registry.registerBeanDefinition("userBeanPost",builder.getBeanDefinition());

                System.out.println("----------#######postProcessBeanDefinitionRegistry------------------"+registry.getBeanDefinitionCount());
                RootBeanDefinition user=new RootBeanDefinition(User.class);
                registry.registerBeanDefinition("userBeanPost",user);
            }

            @Override
            public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                System.out.println("----------#######postProcessBeanFactory------------------"+beanFactory.getBeanDefinitionCount());
            }
        };
    }
  • context.close()

關閉應用。程序結束。

至此,經常使用的context咱們已經演示完畢。

演示項目地址,歡迎fork和star

碼雲:SpringBootLearn

最後

相關文章
相關標籤/搜索