SpringBoot 2.0 系列005

Stella981
• 阅读 669

SpringBoot 2.0 系列005 --启动实战之SpringApplication应用

注意是只使用了@EnableAutoConfiguration,默认是只扫描这一个我们自定义的类到bean中。不含子包和本包。下一篇我们分析原因。

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方法。

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

第一步

创建对象后 返回SpringApplication对象,我们来分析此对象有用的几个方法。

构造方法

实例化SpringApplication对象

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

通过构造方法 我们发现是可以传递多个class对象,即除了传递启动类以外,我们也可以传递其他Class对象 可以是@configuration注解包含的对象 当然也可以是其他注解类型的。

  • 示例

我们可以将UserService.class交给SpringBoot进行管理

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

addPrimarySources 方法

此种方式等价于构造方法方式。可实现多个class注入。

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

setAdditionalProfiles

设置附加的Profiles,个人理解等价于Spring.profiles.active,使用方式如下

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

setBannerMode

设置Banner工作模式 可关闭,也可以在控制台和log中,使用方式如下

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 来配置。

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() { @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

最后

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
3年前
AI研习丨专题:人工智能系统自身的攻防对抗
  !(https://nimg.ws.126.net/?urlhttp%3A%2F%2Fdingyue.ws.126.net%2F2020%2F1022%2F604f209ej00qilujj005wc000rs00fmm.jpg&thumbnail650x2147483647&quality80&typejpg)  近年来,人工智能飞
Wesley13 Wesley13
3年前
1. 容器化部署一套云服务 第一讲 Jenkins(Docker + Jenkins + Yii2 + 云服务器))
容器化部署一套云服务系列1\.容器化部署一套云服务之Jenkins(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.cnblogs.com%2Fjackson0714%2Fp%2Fdeploy1.html)一、购买服务器服务器!caeef00
Wesley13 Wesley13
3年前
Java日期时间API系列35
  通过Java日期时间API系列1Jdk7及以前的日期时间类(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.cnblogs.com%2Fxkzhangsanx%2Fp%2F12032719.html)中得知,Java8以前除了java.sql.Timestamp扩充
Wesley13 Wesley13
3年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这