SpringBoot 2.0 系列005 --启动实战之SpringApplication应用
- 2.X 官方示例
注意是只使用了@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
}
});
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我们已经演示完毕。