Spring IOC - start

本文从常用的Factory入手,详细解析了Spring框架中FileSystemXmlApplicationContext的实现原理。通过分析其构造器源码,阐述了该类如何实现BeanFactory和ResourceLoader接口,并介绍了Spring中资源查找的相关机制。

Spring 使用已经有些年头了,但始终没有静下心来整理 Spring,关于 Spring 各种实现方式也都是大而概之的了解,也没有深入的研究。今天终于鼓起勇气来整理他了。

 

万事开头难,从哪里开始呢,那就从常用的 Factory 开始吧。

在日常的使用中,比较少的直接使用 BeanFactory,常用是 ApplicationContext 接口。下面我们就以FileSystemXmlApplicationContext 为例,开始梳理 Spring 中的依赖注入的知识。

 

首先看看 FileSystemXmlApplicationContext 实现了那些接口、继承了那些基类:

FileSystemXmlApplicationContext Class

上图可以说明 FileSystemXmlApplicationContext 是一个具有完整功能的 BeanFactory,直接可以被客户使用。可以把它分为两部分接口的体现,一方面是 BeanFactory ,另一方面是 ResourceLoader 。前者使其具体 Factory 的相关功能,后者使其具体资源加载的功能。我们在日常中常用的 ApplicationConext 接口是继承与 BeanFactory 的,FileSystemXmlApplicationContext 也实现了这个接口。

 

下面我们分析一下其构造器源码:

// 默认构造器
public FileSystemXmlApplicationContext() {
}

// 指定了父容器的构造器
public FileSystemXmlApplicationContext(ApplicationContext parent) {
	super(parent);
}

// 指定单个的配置文件位置构造器
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
	this(new String[] {configLocation}, true, null);
}

// 指定多个配置文件位置构造器,默认需要刷新容器
public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
	this(configLocations, true, null);
}

// 指定了配置文件和父容器的构造器,默认需要刷新容器
public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
	this(configLocations, true, parent);
}

// 指定了配置文件位置以及是否需要刷新的构造器
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
	this(configLocations, refresh, null);
}

// 核心构造器,设置了Bean配置文件位置、是否需要刷新容器、父容器的构造器
// 如果配置了需刷新容器,则调用刷新接口。
// refresh方法是由AbstractApplicationContext提供,后面的笔记中应该相信说明这方法(后续附上链接)
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
		throws BeansException {

	super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();
	}
}

 FileSystemXmlApplicationContext 定义是很简单,他其中关于 Bean 的资源查找、解析、注册都有其父类完成。

 

Spring 中关于资源的查找是很大一部分内容,这部分功能大部分是依赖 DefaultResourceLoader 的实现,下次主要说明 Spring 是如何加载资源文件的。

### Spring 中的 IOC 和 AOP #### 控制反转 (IoC) 控制反转(Inversion of Control, IoC)是一种设计思想,旨在将对象创建和依赖关系管理的责任从应用程序内部转移到外部容器。通过这种方式,可以实现更松散耦合的设计[^2]。 在 Spring 框架中,IoC 容器负责管理和实例化被称为 **Spring Beans** 的组件。这些 Bean 是由容器自动装配并注入到其他 Bean 中使用的对象。简单来说,IoC 容器就像是一个大型工厂,它知道如何构建所有的部件并将它们组装在一起形成完整的系统[^1]。 具体而言,在 Spring 中可以通过 XML 配置文件定义 Bean 及其属性: ```xml <bean id="book" class="com.cztu.tdj.spring5.Book"> <property name="bname" value="tdj"/> <property name="bauthor" value="javaSpring"/> </bean> ``` 这段代码展示了如何在一个名为 `book` 的 bean 上设置两个属性——书名 (`bname`) 和作者 (`bauthor`)。这表明了即使不直接调用构造函数也可以完成对象初始化过程[^3]。 除了基于 XML 的配置外,现代版本的 Spring 更推荐使用 Java 注解来简化配置工作量。例如: ```java @Component public class Book { private String bname; private String bauthor; @Autowired public Book(String bname, String bauthor){ this.bname = bname; this.bauthor = bauthor; } } ``` 这里利用了 `@Component` 来标记类作为可被扫描注册成 Bean 的候选者;而 `@Autowired` 则用于指示参数应该由 Spring 自动解析并注入相应的值。 #### 面向切面编程 (AOP) 面向切面编程(Aspect-Oriented Programming, AOP)允许开发者分离横切关注点(cross-cutting concerns)。所谓横切逻辑是指那些跨越多个模块的功能需求,如日志记录、事务处理等。借助于 AOP 技术可以在不影响业务流程的前提下增强现有功能而不必修改源码本身。 为了实现这一点,Spring 提供了一套强大的 API 支持编写 AspectJ 或自定义切入点表达式的方面定义。下面是一个简单的例子展示如何为服务层的方法添加环绕通知: ```java import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Around; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { @Around("execution(* com.example.service.*Service.*(..))") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); try { return joinPoint.proceed(); // 执行目标方法 } finally { long executionTime = System.currentTimeMillis() - start; System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms"); } } } ``` 上述代码片段中的 `LoggingAspect` 类实现了对指定包下所有 Service 接口方法执行时间的日志记录操作。每当匹配的服务方法被执行时,都会触发该方面的行为,并打印出耗时信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值