1 Spring 注解的使用
1 IOC 的概念
IOC(Inversion of Control):控制反转。
- 使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。通俗的讲就是"将new对象的权利交给Spring,我们从Spring中获取对象使用即可"
Spring技术对 IOC 思想进行了实现
- Spring提供了一个容器,称为IOC容器,用来充当IoC思想中的"外部"
- IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
DI(Dependency Injection):依赖注入
- 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。
2 使用简单的案例实现注解的使用
案例的代码文件的结构:
(1)dao层:
java
package com.xbf.dao;
public interface BookDao {
void saveBook();
}
(2)service层:
java
package com.xbf.service;
public interface BookService {
void insertBook();
}
(3)其他实现类
@Configuration
:注解用于标记一个类为配置类,表示该类包含Bean的定义。
@ComponentScan
:告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器。
java
@Configuration //标记该类为spring配置类
@ComponentScan({"com.xbf.dao","com.xbf.service"})
//如果扫描多个类,形如:
// @ComponentScan({"a", "b"})
//简单理解就是,传入一个静态数组
public class SpringConfig {
}
@Componet
: 在Spring框架中,@Component注解是一个非常核心的概念,它用于将类标记为Spring容器中的一个Bean。这个注解告诉Spring,当应用启动时,需要在ApplicationContext中创建这个类的一个实例。这个过程是自动的,不需要显式编写代码来创建对象。
java
@Component
public class BookDaoImpl implements BookDao {
@Override
public void saveBook() {
System.out.println("我是BookDaoImpl类的saveBook()方法");
}
}
@Autowired
:在Spring框架中,@Autowired注解是实现依赖注入(DI)的重要工具。它可以自动地将定义好的Bean注入到Spring容器中的其他Bean中。这个注解可以用于成员变量、方法和构造函数上,从而省去了手动编写大量的获取依赖和赋值代码。
@Component
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
@Override
public void insertBook() {
bookDao.saveBook();
System.out.println("我是BookServiceImpl类的方法insert()");
}
}
代码运行:
public class App {
public static void main(String[] args) {
//加载核心配置文件
ClassPathXmlApplicationContext ioc = new
ClassPathXmlApplicationContext("Spring-Context.xml");
//从ioc 容器中获取bean对象
//BookDao bookDao = (BookDao) ioc.getBean("bookDao");
//bookDao.addBook();
// 获取 BookService 实例
BookService bookService = (BookService) ioc.getBean("bookService");
// 调用 BookService 的 insertBook 方法
bookService.insertBook();
}
}
运行结果:
2 SpringAOP 的使用
1 AOP 的基本概念
AOP(Aspect Oriented Programming):面向切面编程,一种编程范式,指导开发者如何组织程序结构
**作用:**在不惊动原始设计的基础上为其进行功能增强。
**Spring理念:**无入侵式/无侵入式
**原理:**动态代理
应用:1. 日志 2. 异常捕获、处理 3. 监控统计代码 4. 记录过程。
一些重要的概念:
- 连接点(JoinPoint):正在执行的方法,例如:update()、delete()、select()等都是连接点。
- 切入点(Pointcut):进行功能增强了的方法,例如:update()、delete()方法,select()方法没有被增强所以不是切入点,但是是连接点。
- 在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法。
- 一个具体方法:com.xbf.dao包下的BookDao接口中的无形参无返回值的save方法。
- 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法。
- 通知(Advice):在切入点前后执行的操作,也就是增强的共性功能。
- 在SpringAOP中,功能最终以方法的形式呈现。
- 通知类:通知方法所在的类叫做通知类。
- 切面(Aspect):描述通知与切入点的对应关系,也就是哪些通知方法对应哪些切入点方法。
2 AOP 的案例实现
写一个计算器功能:计算加除法。并且用日志方式打印传递的参数、和结果、结束后通知用户计算完成!如果出现异常打印异常信息。完成步骤如下:
- 导入aop相关坐标
- 创建配置类进行Spring注解包扫描
- 定义业务接口与实现类
- 定义通知类,制作通知方法
- 定义切入点表达式、配置切面(绑定切入点与通知关系)
- 在配置类中开启AOP功能
案例代码的结构:
(1)导入AOP相关坐标
在 pom.xml 文件中,引入相关依赖:
java
<!-- Spring 框架的核心模块,提供了 Spring 上下文和依赖注入功能 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- Spring 测试模块,提供了测试支持和集成 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- AspectJ 织入器,用于支持 Spring AOP 编程模型 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<!-- JUnit 测试框架,用于编写和运行测试用例 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
(2)创建相关类
- service 层:
接口类:
java
package com.xbf.service;
public interface JiSuanQi {
//加法
int add(int a, int b);
//减法
int sub(int a, int b);
//乘法
int mul(int a, int b);
//除法
int div(int a, int b);
}
实现类:
java
package com.xbf.service.impl;
import org.springframework.stereotype.Component;
@Component
public class JiSuanQiImpl implements com.xbf.service.JiSuanQi {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int sub(int a, int b) {
return a - b;
}
@Override
public int mul(int a, int b) {
return a * b;
}
@Override
public int div(int a, int b) {
return a / b;
}
}
- 核心配置类
java
package com.xbf.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan({"com.xbf.service","com.xbf.advice"})
@EnableAspectJAutoProxy //开启 Spring 的 AspectJ 自动代理功能,支持 AOP
public class SpringConfig {
}
- 通知类
java
package com.xbf.advice;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
@Aspect //通知类
public class MyAdvice {
@Pointcut("execution(* com.xbf.service.impl.JiSuanQiImpl.*(int, int))")
public void pointcut(){};
//1.前置通知
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
System.out.println("参数:" + Arrays.toString(joinPoint.getArgs()));
System.out.println("开始计算");
}
//2.后置通知
@After("pointcut()")
public void after() {
System.out.println("计算结束");
}
//3.返回通知
@AfterReturning(value = "pointcut()", returning = "result")
public void afterReturning(Object result) {
System.out.println("计算结果:" + result);
}
//4 异常通知
@AfterThrowing(value = "pointcut()", throwing = "e")
public void afterThrowing(Throwable e) {
System.out.println("异常:" + e.getMessage());
}
}
@Pointcut 注解的解释:
apl
@Pointcut("execution(* com.xbf.service.impl.JiSuanQiImpl.*(int, int))")
public void pointcut(){};
上式:AspectJ 切点表达式,用于定义一个切点(pointcut)。这个切点表达式指定了在哪些方法执行时应用通知。下面是对这段代码的详细解释:
@Pointcut("execution(* com.xbf.service.impl.JiSuanQiImpl.*(int, int))"):这是一个注解,用于定义一个切点。@Pointcut 注解是 AspectJ 框架中的一个特性,它允许你定义一个方法作为切点,然后在其他通知注解(如 @Before、@After、@Around 等)中引用这个切点。
"execution(* com.xbf.service.impl.JiSuanQiImpl.*(int, int))":这是切点表达式的具体内容。它的含义是:匹配 com.xbf.service.impl.JiSuanQiImpl 包中的任意类的任意方法,这些方法接收两个 int 类型的参数。execution 是 AspectJ 中最常用的切点指示器,用于指定方法的执行作为切点。
这个切点表达式定义了一个非常具体的切点,它只匹配 JiSuanQiImpl 类中的那些接收两个 int 参数的方法。在这个切面类 MyAdvice 中,这个切点被用于四个不同的通知注解(@Before、@After、@AfterReturning、@AfterThrowing),这意味着在JiSuanQiImpl 类的这些特定方法执行之前、之后、返回结果后以及抛出异常后,都会执行相应的通知方法。
- 快速生成测试类:
JUnit是一个用于编写和运行可重复的自动化测试的开源测试框架,它是单元测试框架的xUnit架构的一个实例。JUnit主要有两个版本:JUnit 4和JUnit 5。
-
JUnit 4:这是JUnit的一个较早期版本,它支持Java 5及以上版本。JUnit 4引入了注解的使用,使得测试用例的编写更加简洁和直观
。
-
JUnit 5:这是JUnit的最新版本,它在设计上与JUnit 4相比有了重大的改进。JUnit 5的主要目标是支持现代Java开发实践,包括对Java 8及更高版本的支持。
默认会在 src/Test 目录下生成。
java
package com.xbf.service.impl;
import com.xbf.config.SpringConfig;
import com.xbf.service.JiSuanQi;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class JiSuanQiTest {
@Autowired
private JiSuanQi jiSuanQi;
@Test
public void add() {
//System.out.println("加法");
System.out.println(jiSuanQi.add(2,4));
}
@Test
public void sub() {
System.out.println(jiSuanQi.sub(5,9));
}
@Test
public void mul() {
}
@Test
public void div() {
//System.out.println(jiSuanQi.div(5,9));
double n = jiSuanQi.div(5,9);
double m = jiSuanQi.div(5,0);
}
}
注解的解释:
apl
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
Java中的两个注解:用于配置JUnit测试框架与Spring框架的集成。
@RunWith(SpringJUnit4ClassRunner.class):
这个注解是JUnit框架提供的,用于指定测试运行器(Runner)。
SpringJUnit4ClassRunner是Spring框架提供的一个测试运行器,它允许在JUnit测试中使用Spring的依赖注入和事务管理等功能。
通过这个注解,JUnit会自动加载Spring的应用上下文(Application Context),并在测试类中注入Spring管理的Bean。
@ContextConfiguration(classes = SpringConfig.class):
这个注解也是Spring框架提供的,用于指定Spring应用上下文的配置类。
SpringConfig.class 是一个配置类,通常包含了Spring框架的各种配置,如Bean的定义、扫描包路径、数据库连接等。
通过这个注解,JUnit会在运行测试之前加载 SpringConfig 类,并根据其中的配置初始化Spring应用上下文。
这两个注解通常一起使用,确保JUnit测试能够在Spring容器的环境中运行,从而可以使用Spring的依赖注入和其他功能来测试Spring管理的组件。
在这个例子中,JiSuanQiTest 类是一个JUnit测试类,它使用了这两个注解来配置Spring环境,以便能够测试 JiSuanQi 类的功能。