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<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
最后
-
作者ricky
-
交流群:244930845