Spring 源码解析 | 核心功能

57,366 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

Spring 框架是以简化 JAVA EE 应用程序的开发为目标而创建的,它为企业级开发提供了丰富的功能,但这些功能的底层都依赖于他的两个核心特性:依赖注入(DI)和面向切面编程(AOP)。

本文主要是讲 Spring 在项目中 Bean 容器如何初始化。环境概述:

  • JDK 11
  • Spring 5.3.10-SNAPSHOT

简单案例

下面是一个简单的 Spring Bean 容器使用的案例:

// 创建容器
AnnotationConfigApplicationContext applicationContext =  new AnnotationConfigApplicationContext(AppConfig.class);
// 获取 Bean 对象
UserService serviceService = applicationContext.getBean(UserService.class);
// 打印 Bean 对象
System.out.println(serviceService);

在这个例子中,我们可以看到 Spring 的使用非常简单。 往往大家都会有这个问题:我们为什么要使用 Spring? Spring 能给我们提供哪些开发能力?

  1. 还有就是 Spring 本身是一个 Bean 容器,可以帮我们管理对象。例如:默认创建单实例 Bean, 也可以通过标记快速创建原型对象,解决了我们在对象引用,或者对象回收的一系列的问题。
  2. Spring 还能能够提供快速的和三方框架的整合能力比如:MyBatis,MVC,RocketMQ 等常用中间件。

下面我们将从 Bean 的创建, Aop 实现,Transaction 实现等三个方面来学习 Spring 的基本使用。

Bean 创建

Bean 的定义

Spring Bean 是 Spring 通过 Spring 容器创建的 Java 对象。它们被 Spring IOC 容器初始化、装配和管理。这些 Bean 通过容器中配置的元数据创建。

Spring 框架中定义的 Bean 默认都是单例的。可以通过 @Scope("singleton") 注解进行标记,如果需要申明为原型 Bean 那么就可以用 @Scope("prototype")

如何创建 Bean

我们可以在方法上增加 @Bean 注解进行创建 Bean ,或者在类上面增加 @Component � 如下所示:

// bean 注解
@Bean
private UserService user() {
    return new UserService();
}

@Component
public class UserService {
}

Aop 实现

申明切面

@Aspect
public class UserAspect {
	
	//匹配所有ServiceImpl包下面的所有类的所有方法
	@Pointcut("execution(* com.ctc.ServiceImpl.*.*(..))")
	public void addLog(){}
 
}

定义 Advice

Advice注解一共有五种,分别是: 1.@Before前置通知 前置通知在切入点运行前执行,不会影响切入点的逻辑 2.@After后置通知 后置通知在切入点正常运行结束后执行,如果切入点抛出异常,则在抛出异常前执行 3.@AfterThrowing异常通知 异常通知在切入点抛出异常前执行,如果切入点正常运行(未抛出异常),则不执行 4.@AfterReturning返回通知 返回通知在切入点正常运行结束后执行,如果切入点抛出异常,则不执行 5.@Around环绕通知 环绕通知是功能最强大的通知,可以在切入点执行前后自定义一些操作。环绕通知需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行 举个例子:

//使用 addLog 这个切入点进行增强
@Before("addLog()")
public void before() {
    System.out.println("before 前置通知......");
}

使用代理对象

申明 UserService

@Component
public class UserService {

	public void test() {
		System.out.println("orderService:" + orderService);
	}
}

调用 test 方法

public class AopTest {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext =
				new AnnotationConfigApplicationContext(AppConfig.class);
		UserService serviceService = applicationContext.getBean(UserService.class);
		serviceService.test();
	}
}

// AppConfig.java
@Import(UserAspect.class)
@Configurable
public class AppConfig {

	@Bean
	private UserService userService() {
		return new UserService();
	}
}

参考文档