1. 程式人生 > 程式設計 >Springboot-spring高階話題

Springboot-spring高階話題

Spring Aware

一、介紹

Aware:意識到,目的是讓Bean獲得到Spring容器的服務,可以直接繼承ApplicationContextAware獲得Spring容器的所有服務,但原則上是使用到什麼介面,就實現什麼介面。

二、需求

將txt檔案裡面的內容,讀取到控制檯。

三、示例

1.新建test.txt檔案,內容隨意
1234567890qwertyuiop!@#$%^&*()去沃爾特與IOP平
複製程式碼
2.Spring Aware演示Bean
package com.eleven.aware1;

import java.io.IOException;

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; @Service // 表示將當前類注入到Spring容器中,成為Spring管理的一個Bean
// BeanNameAware:獲得到容器中Bean的名稱 // ResourceLoaderAware:獲取外部資原始檔 public class AwareService implements BeanNameAware,ResourceLoaderAware { private String beanName; private ResourceLoader loader; @Override public void setResourceLoader(ResourceLoader resourceLoader) { // TODO Auto-generated method stub
this.loader = resourceLoader; } @Override public void setBeanName(String name) { // TODO Auto-generated method stub this.beanName = name; } public void outputResult() { // 獲取到檔案的名稱 System.out.println("Bean的名稱:" + beanName); // 載入外部資原始檔 Resource resource = loader.getResource("classpath:com/eleven/aware1/test.txt"); // 輸出資原始檔的內容 try { System.out.println("輸出資原始檔的內容:" + IOUtils.toString(resource.getInputStream())); } catch (IOException e) { e.printStackTrace(); } } } 複製程式碼
3.配置類
package com.eleven.aware1;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration	// 宣告當前類是一個配置類
@ComponentScan("com.eleven.aware1")	// 自動掃描包下面的所以配置
public class AwareConfig {

}
複製程式碼
4.執行
package com.eleven.aware1;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
	public static void main(String[] args) {
		// 將AnnotationConfigApplicationContext注入到Spring容器裡面,成為Spring管理的一個Bean
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AwareConfig.class);
		// 獲得AwareService宣告的Bean
		AwareService awareService = context.getBean(AwareService.class);

		awareService.outputResult();
		context.close();
	}

}
複製程式碼
5.輸出
Bean的名稱:awareService
輸出資原始檔的內容:1234567890qwertyuiop!@#$%^&*()去沃爾特與IOP平
複製程式碼

多執行緒

一、介紹

Spring是通過任務執行器(TaskExecutor)來實現多執行緒和併發程式設計。使用ThreadPoolTaskExecutor可以實現一個基於執行緒的TaskExecutor。

二、需求

實現一個多執行緒。

三、示例

1.配置類
package com.eleven.thread1;

import java.util.concurrent.Executor;

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;

@Configuration // 宣告當前類是一個配置類
@ComponentScan("com.eleven.thread1") // 自動掃描包下面的所有配置
@EnableAsync // 開啟非同步任務支援
public class TaskExecutorConfig implements AsyncConfigurer {

	@Override
	public Executor getAsyncExecutor() {
		// TODO Auto-generated method stub
		ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); // 執行緒池
		taskExecutor.setCorePoolSize(5);	// 核心池大小
		taskExecutor.setMaxPoolSize(10);	// 最大池大小
		taskExecutor.setQueueCapacity(25);	// 排隊容量
		taskExecutor.initialize();			// 初始化
		return taskExecutor;
	}

	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		// TODO Auto-generated method stub
		return null;
	}

}
複製程式碼
2.任務執行類
package com.eleven.thread1;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service // 宣告當前類是Spring管理的一個Bean
public class AsynTaskService {

	@Async	// 表示該方法是非同步方法
	public void executeAsyncTask(Integer i) {
		System.out.println("執行非同步任務" + i);
	}

	@Async
	public void executeAsyncTaskPlus(Integer i) {
		System.out.println("執行非同步任務+1++++++++++" + (i + 1));
	}

}
複製程式碼
3.執行
package com.eleven.thread1;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskExecutorConfig.class);
		AsynTaskService asynTaskService = context.getBean(AsynTaskService.class);

		for (int i = 0; i < 10; i++) {
			asynTaskService.executeAsyncTask(i);
			asynTaskService.executeAsyncTaskPlus(i);
		}

		context.close();
	}

}
複製程式碼
4.輸出
執行非同步任務+1++++++++++1
執行非同步任務+1++++++++++3
執行非同步任務2
執行非同步任務+1++++++++++4
執行非同步任務4
執行非同步任務+1++++++++++5
執行非同步任務5
執行非同步任務+1++++++++++6
執行非同步任務+1++++++++++2
執行非同步任務6
執行非同步任務0
執行非同步任務1
執行非同步任務3
執行非同步任務8
執行非同步任務+1++++++++++8
執行非同步任務+1++++++++++10
執行非同步任務7
執行非同步任務+1++++++++++7
執行非同步任務9
執行非同步任務+1++++++++++9
複製程式碼

計劃任務

一、介紹

在配置類上加入@EnableScheduling註解,開啟對計劃任務的支援,然後在要執行計劃任務的方法上加入@Scheduled註解,宣告是一個計劃任務。

二、需求

利用Spring的計劃任務,每隔5秒執行一次。

三、示例

1.計劃任務執行類
package com.eleven.planttask1;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service // 宣告當前類是一個配置類
public class ScheduledTaskService {

	// 獲取當前時間
	private static final SimpleDateFormat dataFormat = new SimpleDateFormat("HH:mm:ss");

	@Scheduled(fixedRate = 5000) // 開啟計劃任務,預設單位是毫秒
	public void reportCurrentTime() {
		System.out.println("每隔5秒執行一次:" + dataFormat.format(new Date()));
	}

	@Scheduled(cron = "0 28 11 ? * *") // 設定的是每天的11點28分開始執行
	public void fixTimeExecution() {
		System.out.println("在指定的時間:" + dataFormat.format(new Date() + "執行"));
	}

}
複製程式碼
2.配置類
package com.eleven.planttask1;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration // 宣告當前類是一個配置類
@ComponentScan("com.eleven.planttask1")
@EnableScheduling // 開啟對計劃任務的支援
public class TaskSchedulerConfig {

}
複製程式碼
3.執行
package com.eleven.planttask1;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskSchedulerConfig.class);
	}

}
複製程式碼
4.輸出
每隔5秒執行一次:19:54:06
每隔5秒執行一次:19:54:11
每隔5秒執行一次:19:54:16
每隔5秒執行一次:19:54:21
每隔5秒執行一次:19:54:26
複製程式碼

條件註解

一、介紹

根據特定條件建立特定的Bean。

根據特定條件來控制Bean的建立行為。

二、需求

模擬程式在不同的作業系統中,若在Windows系統下執行程式,則輸出命令dir;若在Linux系統下執行,則輸出列表命令ls。

三、示例

1.判斷Windows的條件
package com.eleven.conditional1;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsConditional implements Condition {

	/**
	 * ConditionContext:條件
	 * getEnvironment:獲取環境
	 * getProperty:獲取屬性
	 * contains:包含
	 */
	@Override
	public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) {
		return context.getEnvironment().getProperty("os.name").contains("Windows");
	}

}
複製程式碼
2.判定Linux的條件
package com.eleven.conditional1;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class LinuxConditional implements Condition {

	@Override
	public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) {
		return context.getEnvironment().getProperty("os.name").contains("Linux");
	}

}
複製程式碼
3.介面
package com.eleven.conditional1;

public interface ListService {
	public String showListCmd();

}
複製程式碼
4.windows下所要建立的Bean的類
package com.eleven.conditional1;

import org.springframework.stereotype.Service;

@Service
public class WindowsListService implements ListService{

	@Override
	public String showListCmd() {
		return "dir";
	}

}
複製程式碼
5.Linux下所要建立的Bean的類
package com.eleven.conditional1;

import org.springframework.stereotype.Service;

@Service
public class LinuxListService implements ListService{

	@Override
	public String showListCmd() {
		return "ls";
	}
	
}
複製程式碼
6.配置類
package com.eleven.conditional1;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration // 宣告當前類是一個配置類
public class ConditionConfig {

	@Bean
	@Conditional(WindowsConditional.class)
	public ListService windowsListService() {
		return new WindowsListService();
	}

	@Bean
	@Conditional(LinuxConditional.class)
	public ListService linuxListService() {
		return new LinuxListService();
	}

}
複製程式碼

7.執行

package com.eleven.conditional1;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConfig.class);
		WindowsListService windowsListService = context.getBean(WindowsListService.class);

		System.out.println(
				context.getEnvironment().getProperty("os.name") + "系統下的命令列表為:" + windowsListService.showListCmd());

		/*
		 * LinuxListService linuxListService = context.getBean(LinuxListService.class);
		 * System.out.println( context.getEnvironment().getProperty("os.name") +
		 * "系統下的命令列表為:" + linuxListService.showListCmd());
		 */
	}

}
複製程式碼

8.輸出

Windows 10系統下的命令列表為:dir
複製程式碼

組合註解和元註解

一、介紹

元註解:可以注入到別的註解上的註解。

組合註解:被註解的註解叫做組合註解。

二、需求

模擬一個元註解和組合註解

三、示例

1.組合註解
package com.eleven.annotation1;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Target(ElementType.TYPE)	// 用於介面、類、列舉、註解
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@ComponentScan
public @interface WiselyConfiguration {
	
	String[] value() default{};

}

複製程式碼
2.演示服務Bean
package com.eleven.annotation1;

import org.springframework.stereotype.Service;

@Service
public class DemoService {
	public void outputResult() {
		System.out.println("從組合配置一樣可以獲得Bean");
	}

}

複製程式碼
3.配置類
package com.eleven.annotation1;

@WiselyConfiguration("com.eleven.annotation1")
public class DemoConfig {

}

複製程式碼
4.執行
package com.eleven.annotation1;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

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();
	}

}
複製程式碼
5.輸出
從組合配置一樣可以獲得Bean
複製程式碼

測試

一、介紹

單元測試:只針對當前的類和方法進行測試。

整合測試:將系統的各個部分組合在一起進行測試。

二、需求

將系統的各個部分組合在一起進行整合測試。

三、示例

1.新增依賴包
<!-- Spring Test 支援 -->
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.1.6.RELEASE</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/junit/junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
複製程式碼
2.編寫測試程式碼(在src/main/java)
package com.eleven.test1;

public class TestBean {

	private String content;

	public TestBean(String content) {
		super();
		this.content = content;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}
	
	

}

複製程式碼
3.配置類
package com.eleven.test1;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration // 宣告當前是一個配置類
public class TestConfig {

	@Bean
	@Profile("dev")
	public TestBean devTestBean() {
		return new TestBean("開發環境");
	}

	@Bean
	@Profile("prod")
	public TestBean prodTestBean() {
		return new TestBean("生產環境");
	}

}

複製程式碼
4.測試(在src/test/java下面操作)
package com.eleven.test1;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class) // 在JUint環境下面
@ContextConfiguration(classes = { TestConfig.class }) // 載入配置檔案TestConfig
@ActiveProfiles("prod") // 宣告當前的環境
public class DemoTest {
	@Autowired
	private TestBean testBean;

	@Test
	public void prodTest() {
		String expected = "生產環境";
		String actual = testBean.getContent();
		Assert.assertEquals(expected,actual);
	}

}

複製程式碼
5.輸出
執行測試,為綠色表示通過,紅色表示未通過。
複製程式碼