3.1 SpringAware
3.1.1 说明
Spring的依赖注入的最大亮点就是你所有的Bean对Spring容器的存在是没有意识的。Bean之间的耦合度很低。若使用了SpringAware,将会使得Bean和Spring框架耦合。
Bean | 说明 |
---|---|
BeanNameAware | 获得容器中Bean的名称 |
BeanFactoryAware | 获得当前的BeanFactory,调用容器的服务 |
ApplicationContextAware | 当前的Application Context,调用容器的服务 |
MessageSourceAware | 获得Message Source,获得文本信息 |
ApplicationEventPublisherAware | 应用事件发布器,可以发布事件 |
ResourceLoaderAware | 获得资源加载器,可以获取外部资源文件 |
Spring Aware的目的是为了让Bean获取Spring容器的服务。
3.1.2 实例
1)新增资源aware.txt
Hello,this is a Spring Aware test!
2)Bean的创建
package com.dy.spring_demo.ch3.aware;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
/**
* Author:dy_bom
* Description: 实现BeanNameAware、ResourceLoaderAware接口,获取Bean名称和资源加载的服务。
* Date:Created in 上午1:07 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
@Service
public class AwareService implements BeanNameAware, ResourceLoaderAware {
private String beanName;
private ResourceLoader resourceLoader;
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public String getBeanName() {
return beanName;
}
public ResourceLoader getResourceLoader() {
return resourceLoader;
}
public void outResult(){
System.out.println("Bean的名称是:"+beanName);
Resource resource = resourceLoader.getResource("classpath:com/dy/spring_demo/ch3/aware/aware.txt");
try {
System.out.println("ResourceLoader加载的文件内容为:"+ IOUtils.toString(resource.getInputStream(), Charsets.requiredCharsets().lastKey()));
}catch (Exception e){
e.printStackTrace();
}
}
}
3)配置
package com.dy.spring_demo.ch3.aware;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午1:15 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
@Configuration
@ComponentScan("com.dy.spring_demo.ch3.aware")
public class AwareConfig {
}
4)运行
package com.dy.spring_demo.ch3.aware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午1:16 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AwareConfig.class);
AwareService awareService = context.getBean(AwareService.class);
awareService.outResult();
context.close();
}
}
结果如下
Bean的名称是:awareService
ResourceLoader加载的文件内容为:Hello,this is a Spring Aware test!
3.3 多线程
3.3.1 说明
Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程。使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor。通过注解@EnableAsync开启对异步任务的支持,并通过在实际执行的Bean中使用@Async注解来声明其是一个异步任务。
3.3.2 实例
1)配置类
package com.dy.spring_demo.ch3.taskexecutor;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* Author:dy_bom
* Description: 实现AsyncConfigurer重写方法
* Date:Created in 上午1:24 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
@Configuration
@ComponentScan("com.dy.spring_demo.ch3.taskexecutor")
@EnableAsync //开启对异步任务的支持
public class TaskExecutorConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(10);
taskExecutor.setQueueCapacity(25);
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
2)Bean的创建
package com.dy.spring_demo.ch3.taskexecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午1:28 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
@Service
public class AsyncTaskService {
@Async //表明该方法是一个异步方法,注解在类级别,表明该类所有的方法都是异步方法
public void executorAsyncTask(Integer i){
System.out.println("执行异步任务:"+i);
}
@Async
public void executorAsyncTaskPlus(Integer i){
System.out.println("执行异步任务+1:"+(i+1));
}
}
3)运行
package com.dy.spring_demo.ch3.taskexecutor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午1:32 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskExecutorConfig.class);
AsyncTaskService asyncTaskService = context.getBean(AsyncTaskService.class);
for (int i=0;i<10;i++) {
asyncTaskService.executorAsyncTask(i);
asyncTaskService.executorAsyncTaskPlus(i);
}
context.close();
}
}
结果如下
执行异步任务:1
执行异步任务+1:1
执行异步任务+1:2
执行异步任务:2
执行异步任务:0
执行异步任务+1:4
执行异步任务:4
执行异步任务:3
执行异步任务+1:3
执行异步任务:6
执行异步任务+1:6
执行异步任务:5
执行异步任务+1:5
执行异步任务:8
执行异步任务+1:8
执行异步任务:7
执行异步任务+1:7
执行异步任务+1:10
执行异步任务:9
执行异步任务+1:9
结果是并发执行而不是顺序执行
3.3 计划任务
3.3.1 说明
首先在配置类注解@EnableSchedule开启对计划任务的支持,然后在需要执行计划任务的方法上注解@Scheduled,声明这是一个计划任务。
3.3.2 实例
1)配置
package com.dy.spring_demo.ch3.taskscheduler;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午1:44 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
@Configuration
@ComponentScan("com.dy.spring_demo.ch3.taskscheduler")
@EnableScheduling //开启对执行任务的支持
public class TaskSchedulerConfig {
}
2)Bean
package com.dy.spring_demo.ch3.taskscheduler;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午1:39 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
@Service
public class ScheduledTaskService {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss ");
@Scheduled(fixedRate = 5000) // 声明方法是执行任务,使用fixedRate属性每隔固定事件执行
public void reportCurrentTime(){
System.out.println("每隔5秒执行一次:"+dateFormat.format(new Date()));
}
@Scheduled(cron = "0 51 01 ? * *") // 使用Corn属性按照指定时间执行,每天01点51分执行
public void fixTimeExecution(){
System.out.println("在指定时间:"+dateFormat.format(new Date())+"执行");
}
}
3)执行
package com.dy.spring_demo.ch3.taskscheduler;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午1:45 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskSchedulerConfig.class);
}
}
结果如下:
每隔5秒执行一次:01:50:37
每隔5秒执行一次:01:50:42
每隔5秒执行一次:01:50:47
每隔5秒执行一次:01:50:52
每隔5秒执行一次:01:50:57
在指定时间:01:51:00 执行
每隔5秒执行一次:01:51:02
每隔5秒执行一次:01:51:07
每隔5秒执行一次:01:51:12
每隔5秒执行一次:01:51:17
3.4 条件注解@conditional
3.4.1 说明
注解Conditional根据满足某一个特定条件创建一个特定的Bean。例如,不同分操作系统作为条件,我们将通过实现Condition接口,并重写matches方法来判断调条件。此处不做举例说明
3.5 组合注解与元注解
3.5.1 说明
元注解就是可以注解到其他注解上面的注解,被注解的注解称之为组合注解。组合注解具备注解上其他元注解的功能,例如@RestController(@Controller+@ResponseBody)、。
3.5.2 实例
我们来做一个把@Configuration、 @ComponentScan组合注解
1)组合注解
package com.dy.spring_demo.ch3.annotation;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.lang.annotation.*;
/**
* Author:dy_bom
* Description: 组合注解 @Configuration @ComponentScan
* Date:Created in 上午2:02 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@ComponentScan
public @interface DyConfiguration {
String[] value() default {}; //覆盖Value参数
}
2)配置
package com.dy.spring_demo.ch3.annotation;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午2:06 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
@DyConfiguration("com.dy.spring_demo.ch3.annotation")
public class DemoConfig {
}
3)Bean
package com.dy.spring_demo.ch3.annotation;
import org.springframework.stereotype.Service;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午2:04 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
@Service
public class DemoService {
public void outputResult(){
System.out.println("从组合注解可以获取Bean");
}
}
4)执行
package com.dy.spring_demo.ch3.annotation;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Author:dy_bom
* Description:
* Date:Created in 上午2:08 2018/4/2
* Copyright (c) xdy_0722@sina.com All Rights Reserved.
*/
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
DemoService demoService = context.getBean(DemoService.class);
demoService.outputResult();
context.close();
}
}
结果如下:
从组合注解可以获取Bean
代码地址:点我
上一篇:Spring常用配置