人们眼中的天才之所以卓越非凡,并非天资超人一等而是付出了持续不断的努力。1万小时的锤炼是任何人从平凡变成超凡的必要条件。———— 马尔科姆·格拉德威尔

🌟 嗨,我是Xxtaoaooo!
本系列将用源码解剖+拆分核心轮子的方式,带你暴力破解Spring底层逻辑。 警告:阅读后可能导致看Spring源码时产生「庖丁解牛」般的快感! 话不多说,直接开干!
作为数年Java程序猿,我曾陷入“会用Spring却不懂Spring”的尴尬境地。当@Autowired突然失效、事务注解不回滚时,盲目搜索解决方案的挫败感让我决心撕开Spring的优雅封装。本系列文章正是我个人深入了解源码后提炼的核心设计精华,你将看到:


ApplicationContext作为中央工厂,替代传统的new对象方式// 反射实现Bean实例化简化代码
public class SimpleBeanFactory {
private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
public Object getBean(String beanName) throws Exception {
Object bean = singletonObjects.get(beanName);
if (bean != null) return bean;
// 反射创建对象(简化版)
Class<?> clazz = Class.forName(beanName);
bean = clazz.getDeclaredConstructor().newInstance();
singletonObjects.put(beanName, bean);
return bean;
}
}
1. A[启动 refresh() 方法]:
new ClassPathXmlApplicationContext(...)还是new AnnotationConfigApplicationContext(...),最终都会调用refresh()方法来启动容器。2. B[创建并准备 BeanFactory]:
BeanFactory是Spring IoC容器的核心。在此阶段,会创建一个DefaultListableBeanFactory实例,并对其进行一些基础设置,比如设置类加载器。3. C[扫描并加载 BeanDefinitions]:
@Component/@Service等),将找到的Bean解析成BeanDefinition对象。BeanDefinition是Bean的“蓝图”或“配方”,包含了Bean的类名、作用域、依赖关系、属性等元数据。这些BeanDefinition会被注册到BeanFactory中。4. D[注册 BeanPostProcessors]:
BeanPostProcessor是Spring提供的一个强大扩展点,它允许在Bean实例化、配置和初始化前后进行自定义处理(例如,AOP就是通过它实现的)。BeanPostProcessor接口的Bean,并将它们注册到BeanFactory中,以便在后续的Bean创建过程中使用。5. E[初始化所有非懒加载的单例Bean]:
BeanFactory中所有的BeanDefinition,并根据定义创建Bean实例(对于非懒加载的单例Bean)。@PostConstruct方法或afterPropertiesSet方法),以及应用BeanPostProcessor。6. F[发布上下文就绪事件]:
ContextRefreshedEvent事件。总结为:
DefaultListableBeanFactory@Autowired等注解逻辑populateBean()填充属性init-method及@PostConstruct三级缓存是解决循环依赖的核心数据结构:
public class DefaultSingletonBeanRegistry {
// 一级缓存:完整Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存:早期引用(未填充属性)
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 三级缓存:Bean工厂(可生成代理对象)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
}⭐单向对象注入的代码验证
<bean id="userDao" class="org.xt.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="org.xt.service.impl.UserServiceImpl">
<property name="name" value="123"></property>
<property name="userDao" ref="userDao"></property>
</bean>容器中有userDao Bean对象的执行流程:
userDao创建 → userService创建
→ userService执行注入userDao的操作: setUserDao方法执行
<bean id="userService" class="org.xt.service.impl.UserServiceImpl">
<property name="name" value="123"></property>
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="org.xt.dao.impl.UserDaoImpl"></bean>容器中没有userDao Bean对象的执行流程:
userService创建 → userDao创建
→ userService执行注入userDao的操作: setUserDao方法执行
⭐双向对象引用
循环引用(依赖):多个实体之间相互依赖并形成闭环的情况。

⭐循环引用的解决方法:
Spring提供了三级缓存存储完整Bean实例和半成品Bean实例,用于解决循环引用问题。

三级缓存存储未被引用的对象,如果找到未被引用的对象,那么将从三级缓存删除,放入二级缓存,一级缓存是存完成的bean对象。
⭐结合dao和service层循环引用结合三级缓存进行解析:



⭐什么是AOP?
AOP Aspect Oriented Programming 顾名思义就是面向切面编程,是对面向对象编程OOP的一个升华,面向对象编程是纵向对一个事物的抽象,一个对象包括静态属性信息,动态方法信息等。而AOP是横向的对不同事物的抽象,属性与属性、属性与方法、方法与方法、都可以组成一个切面,这种思维去设计编程的方式被称为面向切面编程。


其思想实现方案依靠动态代理技术,在运行期间,对目标对象的方法进行增强,代理对象同名方法内可以执行原有逻辑的同时嵌入执行其他增强逻辑或其他对象的方法。动态代理技术主要依靠Java的反射机制来实现。
Java提供了两种动态代理实现的方式:基于接口的动态代理(JDK动态代理)和基于类的动态代理(CGLIB动态代理)。JDK动态代理只能代理实现了接口的类,而CGLIB动态代理可以代理任意的类,但其原理是通过生成目标类的子类来实现代理。

A对象是目标对象,B对象是增强对象
A对象内部的方法被称为目标方法
B对象内部的方法被称为增强方法
模拟AOP实现的基础代码
public interface UserService {
void show1();
void show2();
}
//目标对象
public class UserServiceImpl implements UserService {
@Override
public void show1() {
System.out.println("show1...");
}
@Override
public void show2() {
System.out.println("show2...");
}
}
//增强类,内部提供增强方法
public class MyAdvice {
public void beforeAdvice(){
System.out.println("前置的增强...");
}
public void afterAdvice(){
System.out.println("后置的增强...");
}
}
public class MockAopBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
ApplicationContext applicationContext;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 目的:对UserServiceImpl中的show1和show2方法进行增强,增强方法存在MyAdvice中
// 问题1:筛选UserServiceImpl或者service.impl包下的所有方法都可以进行增强 解决方案:添加判断
// 问题2:MyAdvice怎么获取到 解决方法:从spring容器中获取
if(bean.getClass().getPackage().getName().equals("org.xt.service.impl")){
//生成当前Bean的Proxy对象
Object beanProxy = Proxy.newProxyInstance(
bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(),
(proxy, method, args) -> {
//执行增强对象的Before方法
MyAdvice myAdvice = applicationContext.getBean(MyAdvice.class);
myAdvice.beforeAdvice();
//执行目标对象的目标方法
Object result = method.invoke(bean, args);
//执行增强对象的After方法
myAdvice.afterAdvice();
return result;
});
return beanProxy;
}
return bean;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}对比维度 | JDK动态代理 | CGLIB |
|---|---|---|
代理对象要求 | 必须实现接口 | 可代理任意类 |
性能 | 调用快,创建慢 | 创建快,调用稍慢 |
底层技术 | Java反射机制 | ASM字节码操作 |
方法拦截器 | InvocationHandler | MethodInterceptor |
适用场景 | 接口-based代理 | 类继承-based代理 |
代理创建核心源码解析
// DefaultAopProxyFactory选择代理方式
public AopProxy createAopProxy(AdvisedSupport config) {
if (config.isOptimize() || config.isProxyTargetClass()) {
return new CglibAopProxy(config); // 使用CGLIB
}
return new JdkDynamicAopProxy(config); // 使用JDK代理
}
// JDK代理调用流程
public Object invoke(Object proxy, Method method, Object[] args) {
// 1. 获取目标对象
Object target = getTarget();
// 2. 获取拦截器链
List<Object> chain = getInterceptorsAndDynamicInterceptionAdvice(method);
// 3. 执行拦截器链
return new ReflectiveMethodInvocation(target, method, args, chain).proceed();
}通知(Advice)执行时序

IOC容器的典型应用

AOP在微服务中的实战
// 分布式事务切面示例
@Aspect
public class GlobalTransactionAspect {
@Around("@annotation(com.distributed.tx)")
public Object handleTransaction(ProceedingJoinPoint joinPoint) {
try {
// 1. 创建全局事务ID
String txId = UUID.randomUUID().toString();
// 2. 通知参与者注册事务
TransactionManager.register(txId);
// 3. 执行目标方法
Object result = joinPoint.proceed();
// 4. 提交事务
TransactionManager.commit(txId);
return result;
} catch (Throwable e) {
// 5. 回滚事务
TransactionManager.rollback(txId);
throw new RuntimeException(e);
}
}
}优秀的框架设计,往往是把复杂留给自己,把简单留给使用者。 Spring的成功正是这一理念的完美实践——通过IoC容器标准化对象生命周期,通过AOP解耦横切关注点,最终实现开发效率的质的飞跃。
回顾本系列的核心收获:
致每一位不甘于CRUD的开发者:撕开框架底层的过程如同攀登技术高原,虽充满挑战,但站在设计思想的顶峰时,你看到的将不再是零散的API,而是一片可自由创造的新大陆。