注意是只使用了@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);
此种方式等价于构造方法方式。可实现多个class注入。
Set primarySources = new LinkedHashSet<>(Arrays.asList(SpringBootApplication05_01.class,UserService.class));
application.addPrimarySources(primarySources);
设置附加的Profiles,个人理解等价于Spring.profiles.active,使用方式如下
//默认执行application-dev.yml文件中的配置
application.setAdditionalProfiles("dev");
设置Banner工作模式 可关闭,也可以在控制台和log中,使用方式如下
application.setBannerMode(Banner.Mode.CONSOLE);// 控制台输出
application.setBannerMode(Banner.Mode.OFF);// 关闭输出
设置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变成上述的形式。
设置启动日志,默认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);
添加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());
}
});
添加监听事件
// 可以监听 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);
}
根据class获取bean对象,是个集合
// 获取所有的User的bean实例
System.out.println(context.getBeansOfType(User.class));
根据BeanName获取bean对象,是单个对象
// 获取beanName是createUser的bean对象
System.out.println("createUser-----------------"+context.getBean("createUser"));
根据class获取bean对象,是单个对象,当有多个是需要使用@Primary
User defaultUser = context.getBean(User.class);
// 此例子是获取到的createUser2对象
System.out.println("User.class-----------------"+defaultUser);
获取已经装载的bean对象
String[] BeanDefinitionNames = context.getBeanDefinitionNames();
System.out.print("包含的bean对象:");
for (String name:BeanDefinitionNames){
System.out.println(name+",");
}
获取应用名称
String applicationName = context.getApplicationName();
System.out.println("applicationName:"+applicationName);
获取bean数量
int beannum=context.getBeanDefinitionCount();
System.out.println("bean的数量:"+beannum);
发布ApplicationEvent 自定义的事件需要在此处发布
// 发布自定义事件
context.publishEvent(new MyApplicationEvent(new Object()));
添加监听
// 等同上述 applicationListener
context.addApplicationListener(applicationListener);
添加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我们已经演示完毕。