Spring 是一款广泛应用于企业级 Java 开发的开源框架,它提供了全面的、高效的、可扩展的解决方案,能够大大简化和加速 Java 应用程序的开发过程。
先看它的架构图:(各层的作用右侧有标明)
- IOC 容器
Spring 的核心特性之一就是控制反转(IoC,Inversion of Control),通过 IoC 容器管理对象的生命周期和依赖关系,使得开发人员只需要关注业务逻辑的实现部分,而无需过多关注对象的创建和管理。常见的 IoC 容器有 BeanFactory 和 ApplicationContext。
- AOP
AOP(Aspect-Oriented Programming)是一种代码编写方式,可以将系统中的横切关注点抽象出来,实现代码的模块化和复用。在 Spring 中,可以使用 AspectJ 或者动态代理实现 AOP。
- Spring MVC
Spring MVC 是 Spring 框架提供的一套 Web MVC 框架,与 Spring 其他模块无缝集成,可以简化 Web 应用程序的开发过程。Spring MVC 采用前端控制器模式,将请求交给一个中央控制器(DispatcherServlet)进行处理,并通过 HandlerMapping、HandlerAdapter 等组件完成具体的请求处理工作。
- JDBC 抽象层
Spring 提供了一个 JDBC 抽象层,可以帮助开发者更加方便地进行数据库操作,并提供了事务管理等基础功能支持。通过 Spring 的 JDBC 抽象层,开发人员可以实现数据访问对象(DAO)模式,将数据访问逻辑和业务逻辑分离。
- 集成其他技术
Spring 可以集成众多开源技术和标准,例如 Hibernate、MyBatis、JPA、JavaMail、Redis、RabbitMQ 等,方便开发者使用和扩展。
- Bean 生命周期
在 Spring 中,Bean 生命周期是指一个 Bean 在 Spring 容器中创建和销毁的过程,包括初始化、使用和销毁三个阶段。在这个过程中,Spring 容器会调用一系列特定的回调方法来完成相关操作,以确保 Bean 能够正确地被创建、初始化和销毁。
- AOP 的实现方式
Spring 实现 AOP 主要有两种方式:静态代理和动态代理。静态代理需要手动编写代理类,而动态代理则不需要手动编写代理类,在运行时动态生成代理类。同时,Spring 还可以与 AspectJ 框架无缝集成,从而实现更为灵活和强大的 AOP 功能。
- 依赖注入(DI)
依赖注入是指 Spring 容器自动将配置文件或者注解中设置的属性值注入到对象中,以完成对对象之间依赖关系的管理。在 Spring 中,常见的依赖注入方式有 Setter 方法注入、构造函数注入和自动装配等。
重点阐述IOC、AOP、DI、Spring事务
- 控制反转(IoC)
控制反转(IoC,Inversion of Control)是 Spring 的核心特性之一。它通过 IoC 容器管理对象的生命周期和依赖关系,使得开发人员只需要关注业务逻辑的实现部分,而无需过多关注对象的创建和管理。在 Spring 中,BeanFactory 和 ApplicationContext 是两种常见的 IoC 容器。BeanFactory 是 Spring 的基本容器,提供了基本的 Bean 容器功能,而 ApplicationContext 是 BeanFactory 的扩展,提供了更多的企业级服务支持,例如国际化、事件机制、AOP 等。
2.依赖注入(DI)
依赖注入(DI,Dependency Injection)是指 Spring 容器自动将配置文件或者注解中设置的属性值注入到对象中,以完成对对象之间依赖关系的管理。在 Spring 中,常见的依赖注入方式有 Setter 方法注入、构造函数注入和自动装配等。
Setter 方法注入是指通过对象的 Setter 方法来完成属性的注入,示例如下:
public class MyService {
private MyDao myDao;
public void setMyDao(MyDao myDao) {
this.myDao = myDao;
}
// ...
}
构造函数注入是指通过对象的构造函数来完成属性的注入,示例如下:
public class MyService {
private MyDao myDao;
public MyService(MyDao myDao) {
this.myDao = myDao;
}
// ...
}
自动装配是指通过注解来自动完成属性的注入,常见的注解有 @Autowired
、@Resource
、@Inject
等。示例如下:
@Service
public class MyService {
@Autowired
private MyDao myDao;
// ...
}
- 面向切面编程(AOP)
面向切面编程(AOP,Aspect-Oriented Programming)是一种代码编写方式,可以将系统中的横切关注点抽象出来,实现代码的模块化和复用。在 Spring 中,可以使用 AspectJ 或者动态代理实现 AOP。
动态代理是指在运行时动态生成代理类,并在其中添加横切逻辑。Spring 中常用的代理方式是 JDK 动态代理和 CGLIB 代理。JDK 动态代理要求被代理的对象必须实现至少一个接口,而 CGLIB 代理则不需要。
AspectJ 是另一种常用的 AOP 框架,它可以与 Spring 无缝集成,提供更为灵活和强大的 AOP 功能。AspectJ 支持更多的切入点表达式、切面优先级等特性,同时也支持静态织入和动态织入两种方式。
总之,控制反转(IoC)、依赖注入(DI)和面向切面编程(AOP)是 Spring 框架的核心特性之一,通过这些功能,Spring 可以帮助开发者更加方便地进行 Java 应用程序的开发和管理。
AOP详解:
Spring AOP(Aspect-Oriented Programming)是 Spring 框架中的一个重要功能,它可以帮助开发人员更加方便地实现面向切面编程(Aspect-Oriented Programming),从而提高代码的可维护性和可扩展性。
AOP 是一种与 OOP 相对应的编程范式。OOP 是通过封装、继承和多态等方式来实现复杂问题的分解和模块化,而 AOP 则是通过横切关注点(Cross-Cutting Concerns)的方式来实现这一目标。横切关注点是指那些在不同对象和方法中都具有共性的逻辑,例如日志记录、事务管理、安全控制等。
Spring AOP 采用代理模式来实现横切关注点的功能。具体来说,当一个类被 Spring 的容器管理后,Spring 会自动为该类生成一个代理对象,并将横切关注点织入到代理对象中,从而实现相应的功能。开发人员可以通过在配置文件或注解中指定切点(pointcut)、通知(advice)等信息来定义需要织入的横切关注点,从而实现面向切面编程。
Spring AOP 中常用的概念包括:
- 切点(Pointcut)
切点是指那些需要被织入横切关注点的方法或对象。Spring AOP 通过切点来定义需要织入的横切关注点。
- 通知(Advice)
通知是指在切点处执行的代码,它包括前置通知、后置通知、环绕通知、返回通知和异常通知等五种类型。
- 切面(Aspect)
切面是由切点和通知组成的一个类,它用于描述对某一类对象或者方法进行织入的规则。
- 连接点(Join Point)
连接点是指程序中可以被代理的方法,它是 Spring AOP 中的一个基本概念。
- 织入(Weaving)
织入是指将横切逻辑应用到目标对象上,并创建新的代理对象的过程。Spring AOP 支持两种织入方式:编译时织入和运行时织入。
总之,在 Spring AOP 中,开发人员可以通过配置文件或注解来定义需要织入的横切关注点,从而实现面向切面编程。Spring AOP 采用代理模式来实现横切关注点的功能,常用的概念包括切点、通知、切面、连接点和织入等。
AOP案例代码:
一个基于 Spring AOP 的简单案例,用于实现对业务层方法的日志记录功能:
- 定义切面类
@Component
@Aspect
public class LogAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);
@Pointcut("execution(* com.example.service..*.*(..))")
public void servicePointcut() {}
@Before("servicePointcut()")
public void before(JoinPoint point) {
LOGGER.info("调用 {} 方法开始", point.getSignature().getName());
}
@AfterReturning(pointcut = "servicePointcut()", returning = "result")
public void afterReturning(JoinPoint point, Object result) {
LOGGER.info("调用 {} 方法结束,返回值为:{}", point.getSignature().getName(), result);
}
@AfterThrowing(pointcut = "servicePointcut()", throwing = "e")
public void afterThrowing(JoinPoint point, Throwable e) {
LOGGER.error("调用 {} 方法发生异常:{}", point.getSignature().getName(), e.getMessage());
}
}
上述代码中,我们定义了一个名为 LogAspect 的切面类,它包含三个通知:
- before:在目标方法执行前打印日志。
- afterReturning:在目标方法正常返回后打印日志。
- afterThrowing:在目标方法抛出异常时打印日志。
2.在 Spring 配置文件中开启 AOP
<aop:aspectj-autoproxy />
3.应用切面
@Service
public class UserServiceImpl implements UserService {
private static final Map<Integer, User> USERS = new HashMap<>();
@Override
public void addUser(User user) {
USERS.put(user.getId(), user);
}
@Override
public User getUserById(int id) {
return USERS.get(id);
}
}
上述代码中,我们定义了一个名为 UserServiceImpl 的业务实现类,并在其中使用了 addUser 和 getUserById 两个方法。我们希望在这些方法执行时自动打印日志,因此需要将 LogAspect 切面应用到 UserServiceImpl 类中。来实现业务功能。
Spring事务:
Spring 事务是 Spring 框架中的一个重要特性,它可以帮助开发人员更加方便地管理数据库事务,并提供了一些事务管理相关的注解和 API 方法。
Spring 支持编程式事务管理和声明式事务管理两种方式。下面分别介绍这两种方式的使用方法。
- 编程式事务管理
编程式事务管理指的是通过编写代码来实现事务控制的方式。在 Spring 中,可以使用 TransactionTemplate 类来进行编程式事务管理。TransactionTemplate 是一个简化了事务管理的模板类,它封装了事务处理的所有逻辑,使得开发者可以专注于业务逻辑的实现。
@Service
public class MyService {
@Autowired
private TransactionTemplate transactionTemplate;
public void save(MyEntity entity) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
myDao.save(entity);
}
});
}
}
Spring中事务的传播特性
在 Spring 框架中,事务的传播行为是指在多个事务之间进行调用时,如何处理这些事务之间的关系和影响。Spring 提供了不同的事务传播行为来控制事务之间的关系。
Spring 支持下列七种传播行为:
- REQUIRED
如果当前方法已经运行在一个事务上下文中,则直接使用该事务;否则,就创建一个新的事务,并在新的事务上下文中执行当前方法。
- SUPPORTS
如果当前方法正在运行在一个事务上下文中,则使用该事务;否则,不使用事务。
- MANDATORY
如果当前方法正在运行在一个事务上下文中,则使用该事务;否则,抛出异常。
- REQUIRES_NEW
创建一个新的事务,并在新的事务上下文中执行当前方法。如果当前方法已经运行在一个事务上下文中,则挂起该事务,并在新的事务上下文中执行当前方法。
- NOT_SUPPORTED
当前方法不应该运行在一个事务上下文中。如果当前正在运行一个事务,则挂起该事务,并在没有事务上下文中执行当前方法。
- NEVER
当前方法不应该运行在一个事务上下文中。如果当前正在运行一个事务,则抛出异常。
- NESTED
如果当前方法正在运行在一个事务上下文中,则在嵌套事务中执行当前方法。嵌套事务拥有一个独立的事务状态,但是它是依赖于外部事务的提交和回滚。如果没有当前事务,则行为与 REQUIRED 一样。
总之,在 Spring 中,使用事务传播行为可以让开发人员控制不同事务之间的关系,从而确保事务管理的正确性和一致性。Spring 提供了七种不同的事务传播行为,开发人员可以根据自己的需要进行选择。
最后补充一下纯注解开发的相关注解知识点:
Spring 是一个开源的、轻量级的 Java 开发框架,使用注解来简化开发过程。下面是 Spring 中常用的一些注解的详解:
-
@Component:标记一个类作为 Spring 组件,可以通过类名自动扫描成为 Spring 的 bean。
-
@Autowired:自动装配,默认按类型进行装配,如果有多个同类型的 bean,则需要指定具体名称或者使用 @Qualifier 注解。
-
@Resource:也是自动装配,默认按照名称进行匹配,支持 JSR-250 规范,常与 @Qualifier 注解搭配使用。
-
@Qualifier:指定具体的 bean 名称,配合 @Autowired 或者 @Resource 使用。
-
@Controller:标记一个类作为 Spring MVC 的 Controller。
-
@Service:标记一个类作为服务层组件。
-
@Repository:标记一个类作为数据访问层组件。
-
@RequestMapping:定义请求的 URL 映射路径和 HTTP 请求方法。
-
@PathVariable:获取 URL 中的参数值。
-
@RequestParam:获取表单提交的参数值。
-
@ResponseBody:将返回结果直接写入 HTTP 响应正文中。
-
@ExceptionHandler:处理异常,可以针对不同的异常类型编写不同的处理逻辑。
-
@Transactional:声明事务,可以在类或者方法上使用,实现数据库操作的事务性。
-
@Configuration:声明配置类。
-
@Bean:声明一个 bean,可以在配置类中使用,相当于 spring-bean.xml 文件中的 <bean> 标签。
-
@Import:导入其他配置类。
-
@Value:获取配置文件中的属性值。
以上是 Spring 中常用的注解。可以根据具体需求灵活运用。