@Async
作用
Springboot提供的一个注解,用于开启线程的异步调用
为什么需要异步调用?
就举一个例子
比如说我们注册账号可以送积分这个场景,注册跟送积分是两个不同的功能,假设注册耗时2秒,送积分耗时3秒,在没有异步机制的时候我们需要耗时5秒,而在异步机制的情况下,只需要耗时3秒即可,这一点就可以很好的提高系统的效率问题,再比如说,如果送积分功能出现了异常,在同步的情况下就有可能阻塞注册功能的进行,而注册功能是这个环节的重点,送积分不是,就有点“因小失大”的感觉,但是在异步的情况下,可以理解成他们是在两个不同的线程中进行,互相不影响,这样一来也就可以很好的解决这个问题,降低耦合
怎么实现
通过@EnableAsync+@Async就可以了
@EnableAsync//开启异步调用
@Configuration
public class config {
}
}
@Service
public class service {
@Async("show")//声明为异步方法
public void show(){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("看。。。。");
}
}
@Controller
public class controller {
@Resource
private service service;
@RequestMapping("/show")
public void show(){
for(int i=0;i<10;i++){
service.show();//这里10个方法都是异步方法,那么就代表着他们10个都可以同时调用
}
System.out.println("123");
}
}
为什么需要给@Async自定义线程池?
改进方法:修改config类
@EnableAsync//开启异步调用
@Configuration
public class config {
@Bean(name = "show")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
// 设置线程池
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 核心线程数
taskExecutor.setCorePoolSize(25);
// 最大线程数
taskExecutor.setMaxPoolSize(50);
// 阻塞队列
taskExecutor.setQueueCapacity(100);
// 允许空闲时间, 超过时间以后空闲的(最大线程-核心线程)会被销毁
taskExecutor.setKeepAliveSeconds(200);
// 线程名字
taskExecutor.setThreadNamePrefix("thread....----");
// 饱和处理机制
// CallerRunsPolicy 重试直到成功为止
// AbortPolicy 丢弃任务并抛异常
// DiscardPolicy 丢弃任务不抛异常
// DiscardOldestPolicy 丢弃阻塞队列中等待最久的那个任务,然后添加这个
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.initialize();
return taskExecutor;
}
}
@Value
作用
给对象赋值
语法
- @Value(“常量”):实现对基本数据类型或String对象的赋值
- @Value(“${XXX}”):从环境变量或者配置文件中读取对应XXX的数据
- @Value(“#{XXX}”):通过Spring的EL表达式,获取bean的属性
public class Person {
//直接注入字符串
@Value("123")
int age;
@Value("你好")
String name;
//通过${}读取配置文件注入(yaml、properties)
@Value("${person.name}")
String desc;
//当该属性在配置文件中不存在时就会报错
// @Value("${person.name22}")
// String desc2;
//通过#{}实现对bean对象的注入
@Value("#{dog111}")
Dog dog;
//计算
@Value("#{2*2}")
int num;
}
@import
作用
将指定类型的对象注入到Spring容器中
实现
@Data
public class man {
private String name;
private int age;
}
@Configuration
@Import(man.class)
public class Config_ {
}
细节
- 使用@import注入的bean的名字是那个类的全类名
- 使用的属性值是默认值
- 如果说@import(XX.class)中,XX实现了ImportSelector接口的话,就不会注入XX这个bean,而是注入其重写的方法 selectImports() 的返回值
@Configuration
@Import(dog.class)
public class Config_ {
}
@Data
public class man {
private String name;
private int age;
}
public class dog implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//传入想要注入的全类名
return new String[]{"com.import_.man"};
}
}
@Configuration+@bean
作用
@Configuration:将一个类声明为配置类
@bean:在配置类下使用,声明在方法上,将一个方法的返回值对象注入到Sping容器中
实现
@Configuration
public class config {
@Bean(name = "person02")
public Person person01(){
return new Person(1,"jack",11);
}
}
- 在不指定名字的情况下(name = “person02”),默认使用方法名作为bean的名字(person01)
- 被@Configuration修饰的类也会一同被注入到spring容器中,名字也是方法名(config )
- @Configuration可以被代替,使用@Component…(那4个都可以)
@conditionBean
作用
bean的条件注入
实现
@Configuration
// @ConditionalOnBean(name = "com.Import.dog")//对该配置类中所有都产生约束
public class conditionBean {
//条件注入
@ConditionalOnBean(name = "man")//当容器中有一个名字叫man的对象时注入dog01
// @ConditionalOnMissingBean(name = "com.Import.dog")//当容器中没有一个名字叫man的对象时注入dog01
// @ConditionalOnClass(value = {dog.class})//当容器中没有dog类型对象时注入dog01
@Bean
public dog dog01(){
dog dog = new dog();
return dog;
}
}