1. 程式人生 > >Spring Boot實戰(1) Spring基礎

Spring Boot實戰(1) Spring基礎

doc 返回值 img utf boot 接口編程 aging 共享 func

1. Spring基礎配置

Spring框架本身有四大原則:

1) 使用POJO進行輕量級和最小侵入式開發

2) 通過依賴註入和基於接口編程實現松耦合

3) 通過AOP和默認習慣進行聲明式編程

4) 使用AOP和模板(template)減少模式化代碼

所謂依賴註入指的是容器負責創建對象和維護對象間的依賴關系,而不是通過對象本身負責自己的創建和解決自己的依賴。依賴註入主要目的是為了解耦。

Spring Ioc容器(ApplicationContext)負責創建Bean,並通過容器將功能類Bean註入到你需要的Bean中。

聲明Bean的註解:

a. @Component組件

b. @Service在業務邏輯層(Service層)使用

c. @Repository在數據訪問層(dao層)使用

e. @Controller在展現層使用

註入Bean的註解,一般情況下是通用的:

a. @Autowired:Spring提供的註解

b. @Resourse: JSR-250提供的註解

c. @Inject: JSR-330提供的註解

示例:

1) 構件maven項目,其pom.xml配置文件如下:

技術分享圖片
  1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd
"> 3 <modelVersion>4.0.0</modelVersion> 4 5 <groupId>com.ws</groupId> 6 <artifactId>study1</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 <packaging>jar</packaging> 9 10 <name>study1</name> 11 <url>http://maven.apache.org</url>
12 13 <properties> 14 <java.version>1.7</java.version> 15 <spring-framework.version>4.1.5.RELEASE</spring-framework.version> 16 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 17 </properties> 18 19 20 <dependencies> 21 <dependency> 22 <groupId>junit</groupId> 23 <artifactId>junit</artifactId> 24 <version>3.8.1</version> 25 <scope>test</scope> 26 </dependency> 27 <dependency> 28 <groupId>org.springframework</groupId> 29 <artifactId>spring-context</artifactId> 30 <version>${spring-framework.version}</version> 31 </dependency> 32 </dependencies> 33 </project> 34
View Code

2) 編寫功能類Bean

技術分享圖片
  1 package com.ws.study.one;
  2 
  3 import org.springframework.stereotype.Service;
  4 
  5 // @Service註解聲明當前FunctionService類是Spring管理的一個Bean
  6 @Service
  7 public class FunctionService {
  8 	public String sayHello(String word){
  9 		return "Hello " + word + " !";
 10 	}
 11 }
View Code

3) 使用編寫好的功能類Bean

技術分享圖片
  1 package com.ws.study.one;
  2 
  3 import org.springframework.beans.factory.annotation.Autowired;
  4 import org.springframework.stereotype.Service;
  5 
  6 // @Service註解聲明當前類是Spring管理的一個Bean
  7 @Service
  8 public class UseFunctionService {
  9 
 10 	// @Autowired實體將FunctionService的實體Bean註入到UseFunctionService中,
 11 	// 進而使UseFunctionService具備FunctionService的功能
 12 	@Autowired
 13 	FunctionService functionService;
 14 
 15 	public String sayHello(String word){
 16 		return functionService.sayHello(word);
 17 	}
 18 }
 19 
View Code

4) 配置類

技術分享圖片
  1 package com.ws.study.one;
  2 
  3 import org.springframework.context.annotation.ComponentScan;
  4 import org.springframework.stereotype.Component;
  5 
  6 // @Component聲明當前類是一個配置類
  7 @Component
  8 // 使用@ComponentScan,自動掃描包下所有使用@Service、@Component、@Repository和@Controller的類,並註冊為Bean
  9 @ComponentScan("com.ws.study.one")
 10 public class DiConfig {
 11 
 12 }
 13 
View Code

5) 運行類

技術分享圖片
  1 package com.ws.study.one;
  2 
  3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  4 
  5 public class Main {
  6 	public static void main(String[] args) {
  7 		// 使用AnnotationConfigApplicationContext作為Spring容器,接受輸入一個配置類作為參數
  8 		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DiConfig.class);
  9 
 10 		// 獲取聲明配置的UseFunctionService的Bean
 11 		UseFunctionService useFunctionService = context.getBean(UseFunctionService.class);
 12 
 13 		System.out.println(useFunctionService.sayHello("di"));
 14 
 15 		context.close();
 16 	}
 17 }
 18 
View Code

6) 運行結果

技術分享圖片
  1 五月 29, 2018 11:07:20 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
  2 信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1fc0f2f: startup date [Tue May 29 23:07:20 CST 2018]; root of context hierarchy
  3 Hello di !
  4 五月 29, 2018 11:07:20 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
  5 信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@1fc0f2f: startup date [Tue May 29 23:07:20 CST 2018]; root of context hierarchy
  6 
View Code

2. Java配置

java配置可以完全替代xml配置,也是Spring Boot推薦的配置方式。java配置是通過@Configuration和@Bean來實現的。

a. @Configuration聲明當前類是一個配置類,相當於一個Spring配置的xml文件

b. @Bean註解在方法上,聲明當前方法的返回值是一個Bean

何時使用java配置或註解配置?原則:全局配置使用java配置(如數據庫配置、MVC相關配置),業務Bean的配置使用註解配置(@Service、@Component、@Repository、@Controller)

示例:

1) 編寫功能類

技術分享圖片
  1 package com.ws.study.javaconfig;
  2 
  3 // 此處沒有@Service聲明的Bean
  4 public class FunctionService {
  5 	public String sayHello(String word){
  6 		return "Hello " + word + " !";
  7 	}
  8 }
  9 
View Code

2) 使用功能類

技術分享圖片
  1 package com.ws.study.javaconfig;
  2 
  3 //此處沒有@Service聲明的Bean
  4 public class UseFunctionService {
  5 	// 此處沒有@Autowired聲明的Bean
  6 	FunctionService functionService;
  7 
  8 	public void setFunctionService(FunctionService functionService) {
  9 		this.functionService = functionService;
 10 	}
 11 
 12 	public String sayHello(String word){
 13 		return functionService.sayHello(word);
 14 	}
 15 }
 16 
View Code

3) 配置類

技術分享圖片
  1 package com.ws.study.javaconfig;
  2 
  3 import org.springframework.context.annotation.Bean;
  4 import org.springframework.context.annotation.Configuration;
  5 
  6 // 使用@Configuration註解聲明當前類是一個配置類。意味著這個類中可能存在0個或多個@Bean註解
  7 // 此處沒有使用包掃描,是因為所有的Bean都在此類中定義了
  8 @Configuration
  9 public class JavaConfig {
 10 
 11 	// 使用@Bean註解聲明當前方法FunctionService的返回值是一個Bean,Bean的名稱是方法名
 12 	@Bean
 13 	public FunctionService functionService(){
 14 		return new FunctionService();
 15 	}
 16 
 17 	@Bean
 18 	public UseFunctionService useFunctionService(){
 19 		UseFunctionService useFunctionService = new UseFunctionService();
 20 		// 註入FunctionService的Bean時候直接調用functionService()
 21 		useFunctionService.setFunctionService(functionService());
 22 		return useFunctionService;
 23 	}
 24 
 25 //	// 另外一種註解方式,直接將FunctionService作為參數給useFunctionService()
 26 //	// 在Spring容器中,只要容器中存在某個Bean,就可以在另外一個Bean的聲明方法的參數中寫入
 27 //	@Bean
 28 //	public UseFunctionService useFunctionService(FunctionService functionService){
 29 //		UseFunctionService useFunctionService = new UseFunctionService();
 30 //		useFunctionService.setFunctionService(functionService);
 31 //		return useFunctionService;
 32 //	}
 33 }
 34 
View Code

4) 運行類

技術分享圖片
  1 package com.ws.study.javaconfig;
  2 
  3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  4 
  5 public class Main {
  6 	public static void main(String[] args) {
  7 		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
  8 
  9 		UseFunctionService useFunctionService = context.getBean(UseFunctionService.class);
 10 
 11 		System.out.println(useFunctionService.sayHello("java config"));
 12 
 13 		context.close();
 14 	}
 15 }
 16 
View Code

5) 運行結果

技術分享圖片
  1 五月 29, 2018 11:36:47 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
  2 信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1fc0f2f: startup date [Tue May 29 23:36:47 CST 2018]; root of context hierarchy
  3 Hello java config !
  4 五月 29, 2018 11:36:47 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
  5 信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@1fc0f2f: startup date [Tue May 29 23:36:47 CST 2018]; root of context hierarchy
  6 
View Code

3. AOP

AOP為面向切面編程,切面編程是指在程序運行期間將某段代碼,動態的切入到某個類的指定方法的指定位置。AOP存在的目的是為了解耦。AOP可以讓一組類共享相同的行為。Spring支持AspectJ的註解式切面編程。

a. 使用@AspectJ聲明是一個切面

b. 使用@After、@Before、@Around定義建言(advice),可直接將攔截規則(切點)作為參數。為了使攔截規則(切點)復用,可使用@PointCut專門定義攔截規則,然後在@After、@Before、@Around的參數中調用。

c. 其中符合條件的每一個被攔截處為連接點(JoinPoint)

Spring本身在事務處理(@Transcational)和數據緩存(@Cacheable)上面都使用註解式攔截。

示例:

1) 添加spring aop支持及AspectJ依賴

技術分享圖片
  1 		<!-- spring aop支持 -->
  2 		<dependency>
  3 			<groupId>org.springframework</groupId>
  4 			<artifactId>spring-aop</artifactId>
  5 			<version>${spring-framework.version}</version>
  6 		</dependency>
  7 		<!-- aspectj支持 -->
  8 		<dependency>
  9 			<groupId>org.aspectj</groupId>
 10 			<artifactId>aspectjrt</artifactId>
 11 			<version>1.8.6</version>
 12 		</dependency>
 13 		<dependency>
 14 			<groupId>org.aspectj</groupId>
 15 			<artifactId>aspectjweaver</artifactId>
 16 			<version>1.8.5</version>
 17 		</dependency>
View Code

2) 編寫攔截規則的註解

技術分享圖片
  1 package com.ws.study.aop;
  2 
  3 import java.lang.annotation.ElementType;
  4 import java.lang.annotation.Retention;
  5 import java.lang.annotation.RetentionPolicy;
  6 import java.lang.annotation.Target;
  7 
  8 // 註解本身沒有功能
  9 // 註解和XML都是元數據
 10 // 註解的功能來自用這個註解的地方
 11 @Target(ElementType.METHOD)
 12 @Retention(RetentionPolicy.RUNTIME)
 13 public @interface Action {
 14 }
 15 
View Code

3) 編寫使用註解的被攔截類

技術分享圖片
  1 package com.ws.study.aop;
  2 
  3 import org.springframework.stereotype.Service;
  4 
  5 @Service
  6 public class DemoAnnotationService {
  7 	@Action(name = "註解式攔截的add操作")
  8 	public void add(){}
  9 }
 10 
View Code

4) 編寫使用方法規則被攔截類

技術分享圖片
  1 package com.ws.study.aop;
  2 
  3 import org.springframework.stereotype.Service;
  4 
  5 @Service
  6 public class DemoMethodService {
  7 	public void add(){}
  8 }
  9 
View Code

5) 編寫切面

技術分享圖片
  1 package com.ws.study.aop;
  2 
  3 import java.lang.reflect.Method;
  4 
  5 import org.aspectj.lang.JoinPoint;
  6 import org.aspectj.lang.annotation.After;
  7 import org.aspectj.lang.annotation.Aspect;
  8 import org.aspectj.lang.annotation.Before;
  9 import org.aspectj.lang.annotation.Pointcut;
 10 import org.aspectj.lang.reflect.MethodSignature;
 11 import org.springframework.stereotype.Component;
 12 
 13 // @Aspect註解聲明一個切面
 14 @Aspect
 15 // @Component讓此切面成為Spring容器管理的Bean
 16 @Component
 17 public class LogAspect {
 18 
 19 	// @Pointcut註解聲明切點
 20 	@Pointcut("@annotation(com.ws.study.aop.Action)")
 21 	public void annotationPointCut(){};
 22 
 23 	// 通過@After註解聲明一個建言,並使用@PointCut定義的切點
 24 	@After("annotationPointCut()")
 25 	public void after(JoinPoint joinpoint){
 26 		MethodSignature signature = (MethodSignature) joinpoint.getSignature();
 27 		Method method = signature.getMethod();
 28 		Action action = method.getAnnotation(Action.class);
 29 		// 通過反射可獲取註解上的屬性,然後做日誌記錄相關的操作
 30 		System.out.println("註解式攔截:"+action.name());
 31 	}
 32 
 33 	// 通過@Before註解聲明一個建言,此建言直接使用攔截規則作為參數
 34 	@Before("execution(* com.ws.study.aop.DemoMethodService.*(..))")
 35 	public void before(JoinPoint joinPoint){
 36 		MethodSignature signature = (MethodSignature)joinPoint.getSignature();
 37 		Method method = signature.getMethod();
 38 		System.out.println("方法規則式攔截: "+method.getName());
 39 	}
 40 }
 41 
View Code

6) 配置類

技術分享圖片
  1 package com.ws.study.aop;
  2 
  3 import org.springframework.context.annotation.ComponentScan;
  4 import org.springframework.context.annotation.Configuration;
  5 import org.springframework.context.annotation.EnableAspectJAutoProxy;
  6 
  7 @Configuration
  8 @ComponentScan("com.ws.study.aop")
  9 // 使用@EnableAspectJAutoProxy註解開啟Spring對AspectJ代理的支持
 10 @EnableAspectJAutoProxy
 11 public class AopConfig {
 12 
 13 }
 14 
View Code

7) 運行類

技術分享圖片
  1 package com.ws.study.aop;
  2 
  3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  4 
  5 public class Main {
  6 
  7 	public static void main(String[] args) {
  8 		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
  9 
 10 		DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);
 11 		demoAnnotationService.add();
 12 
 13 		DemoMethodService demoMethodService = context.getBean(DemoMethodService.class);
 14 		demoMethodService.add();
 15 
 16 		context.close();
 17 	}
 18 
 19 }
 20 
View Code

8) 運行結果

技術分享圖片
  1 五月 30, 2018 10:06:14 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
  2 信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1531931: startup date [Wed May 30 22:06:14 CST 2018]; root of context hierarchy
  3 註解式攔截:註解式攔截的add操作
  4 方法規則式攔截: add
  5 五月 30, 2018 10:12:09 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
  6 信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@1531931: startup date [Wed May 30 22:06:14 CST 2018]; root of context hierarchy
  7 
View Code

Spring Boot實戰(1) Spring基礎