Spring Boot实战 Spring基础
Posted mengrennwpu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot实战 Spring基础相关的知识,希望对你有一定的参考价值。
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
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 }
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
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
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
6) 运行结果
1 五月 29, 2018 11:07:20 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh 2 信息: Refreshing org.spring[email protected]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.spring[email protected]1fc0f2f: startup date [Tue May 29 23:07:20 CST 2018]; root of context hierarchy 6
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
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
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
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
5) 运行结果
1 五月 29, 2018 11:36:47 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh 2 信息: Refreshing org.spring[email protected]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.spring[email protected]1fc0f2f: startup date [Tue May 29 23:36:47 CST 2018]; root of context hierarchy 6
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>
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
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
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
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
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
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
8) 运行结果
1 五月 30, 2018 10:06:14 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh 2 信息: Refreshing org.spring[email protected]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.spring[email protected]1531931: startup date [Wed May 30 22:06:14 CST 2018]; root of context hierarchy 7
以上是关于Spring Boot实战 Spring基础的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 揭秘与实战 数据存储篇 - Redis
es 实战 —— spring boot 中使用 Elasticsearch