您的位置:首页 > 编程语言 > Java开发

SpringBoot系列(2)---无配置文件配置基础2

2017-07-06 15:29 926 查看
上一篇文章的传送门:SpringBoot系列(1)---无配置文件配置基础1

一、Spring Aware 

其实我在写Spring的博客已经用过了SpringAware ,当时使用的是BeanFactoryAware。其实Aware主要为我们提供获得Spring容器信息和服务的接口,让我们可以在bean中获得很多Spring 提供的服务。当然其实直接使用ApplicatonContext已经获得非常多的服务了。

BeanNameAware                         获得容器中Bean的名称

BeanFactoryAware                      获得当前bean factory,使用factory调用容器服务。

ApplicationContextAware             获得当前的application context。

MessageSourceAware      获得message source 获得文本信息

ApplicationEventPublisherAware 应用事件发布器,同样我们可以使用applicationContext 进行事件发布

ResourceLoaderAware           获得资源加载器,用于读取外部资源文件

@Service
public class AwareService implements BeanNameAware,ResourceLoaderAware{

private String beanName;
private ResourceLoader resourceLoader;

public void setBeanName(String s) {
this.beanName = s;
}

public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}

public void test() throws IOException {
System.out.println("Bean name is : " + beanName);
Resource resource = this.resourceLoader.getResource("classpath:text.txt");
System.out.println("text.txt -> " + IOUtils.toString(resource.getInputStream()));
}
}

其中 setBean 和 setResourceLoader 是BeanNameAware 和 ResourceLoaderAware的接口方法。这样我们就可以通过这些方法去获得beanName 和 resourceLoader了。

其实如果我们不去实现ResourceLoaderAware 还可以通过IOC的方式获得ResourceLoader

@Service
public class AwareService implements BeanNameAware{

private String beanName;

@Autowired
private ResourceLoader resourceLoader;

public void setBeanName(String s) {
this.beanName = s;
}

public void test() throws IOException {
System.out.println("Bean name is : " + beanName);
Resource resource = this.resourceLoader.getResource("classpath:text.txt");
System.out.println("text.txt -> " + IOUtils.toString(resource.getInputStream()));
}
}


二、Spring多线程

Spring通过任务执行器TaskExecutor实现多线程和并发编程。使用ThreadPoolTaskExecutor可以实现一个基于线程池的TaskExecutor。

我们需要在配置类加上@EnableAsync 启动异步功能,并创建一个taskExecutor方法,返回一个ThreadPoolTaskExecutor,这样就获得了一个基于线程池的TaskExecutor

@Configuration
@ComponentScan("com.tony")
@EnableAspectJAutoProxy
@EnableAsync
public class ApplicationConfig {

public Executor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}

}


当然我们没有必要使用 executor.execute(new Runnable() {... 去创建一个任务,将这个任务交给Spring。我们只需要在我们的Bean中对需要异步的方法和类打上@Async就完事了。聪明的你已经猜到了,如果在类中打上@Async就代表整个类所有方法都异步,如果在方法上打@Async就代表这个方法是异步。

@Service
public class AsyncTaskService {

@Async
public void executeAsyncTask() throws InterruptedException {
int sum = 0;
for(int i=0;i<1000;i++){
Thread.sleep(10);
sum+= i;
}
System.out.println("executeAsyncTask sum : " + sum);
}

}

Main方法:

public class App
{
public static void main( String[] args ) throws IOException, InterruptedException {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
AsyncTaskService service = context.getBean(AsyncTaskService.class);
service.executeAsyncTask();
System.out.println("main finish !");
}
}

main finish !

executeAsyncTask sum : 499500

Process finished with exit code 0

从输出我们可以看出我们的main方法是没有被阻塞的。

二、@Profile 的升级版 @Conditional

上一篇博客我写了Profile的使用,conditional可以说profile的升级版。conditional可以根据条件获得不同的bean,例如操作系统、日期等等。我们需要实现一个实现condition接口的类。里面会一个matches方法,根据不同的需要放回是否满足条件。

public class WindowsCondition implements Condition {

public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return conditionContext.getEnvironment().getProperty("os.name").toLowerCase().contains("windows");
}
}

public class MacCondition implements Condition {

public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return conditionContext.getEnvironment().getProperty("os.name").toLowerCase().contains("mac");
}
}

我们可以根据不同的操作系统获得不同的bean

然后我定义了一个Bean主要去读取文件内容

@Component
public class TextLoader {

@Autowired
private ResourceLoader resourceLoader;

private String path;

public TextLoader(String path) {
this.path = path;
}

public String fileLoad() throws IOException {
Resource resource = resourceLoader.getResource(this.path);
return IOUtils.toString(resource.getInputStream());
}

}

配置类如下:

@Configuration
@ComponentScan("com.tony")
@EnableAspectJAutoProxy
@EnableAsync
public class ApplicationConfig {

@Bean("textLoader")
@Conditional(WindowsCondition.class)
public TextLoader getWinTextLoader(){
return new TextLoader("file://C:\\text.txt");
}

@Bean("textLoader")
@Conditional(MacCondition.class)
public TextLoader getMacTextLoader(){
return new TextLoader("file:///Users/yanzhichao/Desktop/text.txt");
}
}

如果是windows 系统我会读取C盘下的text.txt文件,如果是mac会读取桌面的text.txt文件,然后看看我们的Main方法:

public static void main( String[] args ) throws IOException, InterruptedException {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
TextLoader loader = context.getBean(TextLoader.class);
System.out.println(loader.fileLoad());
}


三、组合注解

可以看到我们的配置类,一大堆配置就不能少写一点配置吗?或者一次性打一个注解就把所有需要的东西都启动上。嗯~可以

@Configuration
@ComponentScan("com.tony")
@EnableAspectJAutoProxy
@EnableAsync
public class ApplicationConfig {

我们会将以上这些annotation配置写到一个annotation当中:

@Configuration
@ComponentScan()
@EnableAspectJAutoProxy
@EnableAsync
public @interface MyConfig {

//覆盖value参数
String[] value() default{};
}

最后在我们的配置类当中打上我们写的MyConfig即可
@MyConfig("com.tony")
public class ApplicationConfig {


四、Spring Test

在开始之前我们在maven添加SpringTest的依赖支持:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>


然后我们就可以在Junit当中通过依赖注入获得相关的bean并进行测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationConfig.class)
@ActiveProfiles("dev")
public class AppTest  {

@Autowired
private TextLoader textLoader;

@Test
public void testTextLoader() throws IOException {
String textContent = textLoader.fileLoad();
System.out.println("textContent : " +textContent);
Assert.assertEquals("SDFGHJKL\n",textContent);
}

}


@RunWith 没什么好说的,就是要Junit 有SpringTest的支持。

@ActiveProfiles 是需要测试的profile环境

@ContextConfiguration 是配置类

然后直接测试跑就可以了,但是需要注意的是Spring 需要Junit4.12以上的版本的。

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: