Spring 基础配置
Sprin框架本身有四大原则:
- 使用POJO进行轻量级和最小侵入式开发。
- 通过依赖注入和基于接口编程实现松耦合。
- 通过AOP实现默认习惯进行声明式编程。
- 使用AOP和模板(template)减少模块化代码。
Spring 所有的功能的设计和实现都是基于此四大原则的。
1、依赖注入
1.1、理论
我们经常说的控制反转(IOC)和依赖注入(DI)在Spring环境下是两个等同的概念,控制反转是通过依赖注入实现的。所谓依赖注入是指容器在负责创建对象和维护对象间的依赖关系,而不是通过对象本身负责自己的创建和解决自己的依赖。
依赖注入的主要目的是为了解耦,体现了一种“组合”的理念。如果你希望你的类具备一个类的功能如果继承一个父类,子类和父类将耦合,如果组合另外一个类则使耦合度降低。
Spring IOC容器负责创建Bean,并将功能类的Bean注入到你需要的Bean中,Spring可以通过XML配置,注解还有JAVA配置来实现Bean的创建和出入,无能是那种配置,这些配置都被称之为配置元数据,也叫描述数据,意思就是这个数据本身不具备任何执行能力,只能通过外界代码来对这些元数据进行解析后进行一些有意思的数据。
声明Bean的注解:
- @Component 组件,没有明确的角色。
- @Controller 在展现层(MVC→SpringMVC)使用。
- @Service 在业务逻辑层(service层)使用。
- @Repository 在数据访问层(dao层)使用。
注入Bean的注解,一般情况下通用
- @Autowired:Spring提供的注解。
- @Inject:JSR-330提供的注解。
- @Resource:JSR-250提供的注解。
1.2、示例
1)编写功能类的Bean。
package com.wisely.highlight_spring4.ch1.di;
import org.springframework.stereotype.Service;
@Service //使用@Service注解声明当前FunctionService类是Spring管理的一个Bean。其中,使用@Controller、@Service、@Repository和@Controller是等效的,可根据当前Bean在哪一层使用。
public class FunctionService {
public String sayHello(String word){
return "Hello " + word +" !";
}
}
2)使用功能类的Bean。
package com.wisely.highlight_spring4.ch1.di;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service //声明当前类是Spring管理的一个Bean
public class UseFunctionService {
@Autowired //将FunctionService的实体Bean注入到UseFunctionService中
FunctionService functionService;
public String SayHello(String word){
return functionService.sayHello(word);
}
}
3)配置类
package com.wisely.highlight_spring4.ch1.di;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //声明当前类是一个配置类
@ComponentScan("com.wisely.highlight_spring4.ch1.di") //自动扫描包名下所有的@Service、@Component、@Repository、@Controller的类并注册为Bean
public class DiConfig {
}
4)运行
package com.wisely.highlight_spring4.ch1.di;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
//使用AnnotationConfigApplicationContext作为容器,接受一个配置类作为参数拿到上下文对象
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(DiConfig.class);
//获得Bean
UseFunctionService useFunctionService = context.getBean(UseFunctionService.class);
System.out.println(useFunctionService.SayHello("world"));//Hello world !
context.close();
}
}
2、Java配置
2.1、理论
Java配置是Spring4.x推荐的配置方式,可以完全取代xml配置;Java配置也是SpringBoot推荐的配置方式。
Java配置主要是通过@Configuration和@Bean来实现的。
- @Configuration声明当前类是一个配置类,相当于一个Spring里面配置的xml文件。
- @Bean注解在方法上,声明当前方法的返回值是一个Bean。
如果用Java配置替代xml配置的话,那我们主要的原则是:全局配置用Java配置(如数据库相关配置、MVC相关配置),业务Bean的配置使用的是注解配置(@Service、@Component、@Repository、@Controller).
2.2、示例
1)编写功能类的Bean
package com.wisely.highlight_spring4.ch1.javaconfig;
//这里没有用@Service注解声明Bean
public class FunctionService {
public String sayHello(String word){
return "Hello " + word +" !";
}
}
2)使用功能类的Bean
package com.wisely.highlight_spring4.ch1.javaconfig;
//此处没有用@Service声明Bean
public class UseFunctionService {
//此处也没有用@AutoWired注解注入
FunctionService functionService;
public void setFunctionService(FunctionService functionService) {
this.functionService = functionService;
}
public String SayHello(String word){
return functionService.sayHello(word);
}
}
3)配置类
package com.wisely.highlight_spring4.ch1.javaconfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration //声明这是一个配置类,这意味着这个类里面有0个或者多个@Bean注解,此处没有用@ComponentScan包扫描注解
public class JavaConfig {
@Bean //声明当前方法返回的是一个Bean,Bean的名称是方法名
public FunctionService functionService(){
return new FunctionService();
}
@Bean
public UseFunctionService useFunctionService(){
UseFunctionService useFunctionService = new UseFunctionService();
useFunctionService.setFunctionService(functionService()); //注入FunctionService的Bean时候直接调用functionService()。
return useFunctionService;
}
// @Bean
//另外一种注入方式:直接将FunctionService作为参数给useFunctionService(),这也是Spring容器中,只要容器中存在这个Bean,就可以在
//另外一个Bean的声明方法中作为参数注入。
// public UseFunctionService useFunctionService(FunctionService functionService){//4
// UseFunctionService useFunctionService = new UseFunctionService();
// useFunctionService.setFunctionService(functionService);
// return useFunctionService;
// }
}
4)运行
package com.wisely.highlight_spring4.ch1.javaconfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(JavaConfig.class);
UseFunctionService useFunctionService = context.getBean(UseFunctionService.class);
System.out.println(useFunctionService.SayHello("java config"));//Hello java config!
context.close();
}
}
3、AOP
3.1、理论
AOP:面向切面编程,相对于OOP面向对象编程。
Spring的AOP的存在主要是为了解耦。AOP可以让一组类共享共同的行为,在OOP中只能用集成类或者实现接口来实现,这样会是代码的耦合性增强,并且集成只能单继承,阻碍更多的行为添加在一组类上,AOP主要是为了弥补OOP的不足。
Spring支持AspectJ的注解式切面编程。
- 使用@Asopect声明一个切面。
- 使用@After、@Before、@Around定义建言(advice),可以直接将拦截规则(切点)作为参数。
- 其中@After、@Before、@Around参数的拦截规则为切点(PonintCut),为了使切点复用,可以用@PonitCut专门定义拦截规则,然后在@After、@Before、@Around的参数中调用。
4.其中符合条件的每一个被拦截处被称为连接点(JoinPonit)。
3.2、示例
1)pom.xml中添加spring aop支持以及AspectJ依赖
<!-- spring aop支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- aspectj支持 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>
2)编写拦截规则注解(自定义一个注解)
package com.wisely.highlight_spring4.ch1.aop;
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;
//@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
// 作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
// 取值(ElementType)有:
// 1.CONSTRUCTOR:用于描述构造器
// 2.FIELD:用于描述域
// 3.LOCAL_VARIABLE:用于描述局部变量
// 4.METHOD:用于描述方法
// 5.PACKAGE:用于描述包
// 6.PARAMETER:用于描述参数
// 7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
//@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
// 作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
// 取值(RetentionPoicy)有:
// 1.SOURCE:在源文件中有效(即源文件保留)
// 2.CLASS:在class文件中有效(即class保留)
// 3.RUNTIME:在运行时有效(即运行时保留)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
String name();
}
3)编写使用注解的被拦截类
package com.wisely.highlight_spring4.ch1.aop;
import org.springframework.stereotype.Service;
@Service
public class DemoAnnotationService {
@Action(name="注解式拦截的add操作")
public void add(){}
}
4)编写使用方法规则被拦截的类
package com.wisely.highlight_spring4.ch1.aop;
import org.springframework.stereotype.Service;
@Service
public class DemoMethodService {
public void add(){}
}
5)编写切面
package com.wisely.highlight_spring4.ch1.aop;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
@Aspect //声明一个切面
@Component //让此切面成为Spring容器管理的Bean
public class LogAspect {
@Pointcut("@annotation(com.wisely.highlight_spring4.ch1.aop.Action)") //声明切点
public void annotationPointCut(){};
@After("annotationPointCut()") //后置通知
public void after(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Action action = method.getAnnotation(Action.class);
System.out.println("注解式拦截 " + action.name()); //利用反射获得注解上的属性,然后可以做日志相关的操作
}
@Before("execution(* com.wisely.highlight_spring4.ch1.aop.DemoMethodService.*(..))") //前置通知
public void before(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
System.out.println("方法规则式拦截,"+method.getName());
}
}
6)配置类
package com.wisely.highlight_spring4.ch1.aop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch1.aop")
@EnableAspectJAutoProxy //开启Spring对AspectJ支持
public class AopConfig {
}
7)运行
package com.wisely.highlight_spring4.ch1.aop;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AopConfig.class);
DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);
DemoMethodService demoMethodService = context.getBean(DemoMethodService.class);
demoAnnotationService.add();
demoMethodService.add();
context.close();
}
}
原文地址:https://www.cnblogs.com/bigfly277/p/9469990.html