文章目录
一、@ConfigurationProperties和@EnableConfigurationProperties
加载配置到配置类
springboot启动时默认加载application.properties
->@ConfigurationProperties(prefix = "local")
->@EnableConfigurationProperties(Local.class)
// application.properties 中以 local 开头的配置与 Local 实体类进行绑定
@ConfigurationProperties(prefix = "local")
public class Local {
private String host;
private String port;
... 省略 get / set / toString 方法
}
//注解只要能加入到 IOC 容器中,不一定要在启动类上
@EnableConfigurationProperties(Local.class)
public class Springboot01Application {
public static void main(String[] args) {
ConfigurableApplicationContext ioc = SpringApplication.run(Springboot01Application.class, args);
Local local = ioc.getBean(Local.class);
System.out.println(local);
}
}
二、@EnableAsync、@Async实现异步线程池
1.定义异步线程池
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
//定义线程池
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//核心线程数
taskExecutor.setCorePoolSize(10);
//线程池最大线程数
taskExecutor.setMaxPoolSize(30);
//线程队列最大线程数
taskExecutor.setQueueCapacity(2000);
//初始化
taskExecutor.initialize();
return taskExecutor;
}
}
2.使用线程池
@Service
public class AsyncService implements IAsyncService {
@Override
@Async
public void Run() {
System.out.println("线程:" + Thread.currentThread().getName());
}
}
在Controller中调用
@GetMapping("/print_thread")
public String printThread() {
_asyncService.Run();
System.out.println("线程:" + Thread.currentThread().getName());
return "done";
}
3.使用场景
等待子线程完成:阻塞主线程,等待所有子线程执行完毕后继续执行主线程。约等于C#的await Task.WhenAll(tasks);
主线程: CountDownLatch latch=new CountDownLatch(1);
子线程: latch.countDown();
主线程: latch.await();
获取异步结果:子线程返回Future对象,Future<TResult>
约等于C#的Task<TResult>
。
try {
Thread.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("thread", Thread.currentThread().getName());
jsonObject.put("time", System.currentTimeMillis());
return new AsyncResult<String>(jsonObject.toJSONString());
}
通过future.get()获取结果
public void testDealHaveReturnTask() throws Exception {
List<Future> futureList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Future future = asyncTask.dealHaveReturnTask(i*1000);
futureList.add(future);
}
//检查所有子线程是否均执行完毕
while (true) {
boolean isAllDone = true;
String result=Strings.EMPTY;
for (Future future : futureList) {
if (null == future || !future.isDone()) {
isAllDone = false;
}else{
result+=future.get();
}
}
if (isAllDone) {
log.info("所有子线程执行完毕");
log.info("return result is " + result);
break;
}
}
}
三、@EnableScheduling、@Scheduled()实现定时任务
在@SpringBootApplication
所在的启动类加上注解@EnableScheduling
在需要定时执行的方法上加上注解@Scheduled()
@EnableScheduling
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(JkExperimentApplication.class, args);
}
}
定义定时任务
//11:00到11:59点每分钟执行一次
@Scheduled(cron="0 * 11 ** ?")
@Async
public void job(){
System.out.println("测试");
}
四、Java Bean在SpringBoot2.X中的生命周期
1、容器初始化
- 资源定位:Spring通过我们的配置,如
@ComponentScan
定义的扫描路径去找到带有@Component
的类,这个过程就是一个资源定位的过程。 - Bean定义:一旦定位到资源,就开始解析,并且将定义的信息保存起来。注意,此时还没有初始化Bean,有的仅仅是Bean的定义。
- 发布Bean定义:此时,IoC容器也只加载了Bean的定义,还没有Bean的实例生成。
2、依赖注入(DI)
在默认的情况下,Spring会继续去完成Bean的实例化和依赖注入,这样从IoC容器中就可以得到一个依赖注入完成的Bean。
但是有时我们希望某些Bean只是将定义发布到IoC容器而不做实例化和依赖注入,当我们取出来的时候才做初始化和依赖注入等操作。可以通过@ComponentScan
的配置项lazyInit
设置为true
(默认值为false
)。
3、生命周期
Spring在完成依赖注入后,还会进行下图所示流程来完成它的生命周期。
自定义实现某个环节
@Component
public class Person implements BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{
...
}