Spring框架自2003年问世以来,已成为Java企业级开发的事实标准。然而,许多开发者长期处于“会用Spring却不懂Spring”的尴尬境地——当@Autowired突然失效、事务注解不回滚时,只能盲目搜索解决方案。真正的高手,不仅要会用框架,更要理解框架的设计哲学与实现原理。
Spring的核心设计思想可以概括为三点:控制反转(IoC)、依赖注入(DI)和面向切面编程(AOP)。本文将沿着“源码解析→原理剖析→手写实现”的路径,带你彻底吃透Spring的两大核心组件。
在Spring中,所有Bean的配置信息都被抽象为BeanDefinition对象。它是Bean的“蓝图”或“配方”,包含了类名、作用域、依赖关系、初始化方法、销毁方法等所有元数据。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 获取/设置Bean的类名
String getBeanClassName();
void setBeanClassName(String beanClassName);
// 获取/设置作用域
String getScope();
void setScope(String scope);
// 检查是否是单例/原型
boolean isSingleton();
boolean isPrototype();
// 检查是否延迟初始化
boolean isLazyInit();
// 获取属性值
PropertyValues getPropertyValues();
}BeanDefinition接口的设计体现了Spring“约定优于配置”的理念。无论是XML配置、注解配置还是Java配置,最终都会被解析为统一的BeanDefinition对象。
Spring IoC容器的启动入口是refresh()方法——无论是ClassPathXmlApplicationContext还是AnnotationConfigApplicationContext,最终都会调用这个方法。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新上下文
prepareRefresh();
// 2. 创建并准备BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备BeanFactory(设置类加载器、后置处理器等)
prepareBeanFactory(beanFactory);
// 4. 允许子类对BeanFactory进行后置处理
postProcessBeanFactory(beanFactory);
// 5. 调用BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 初始化特定子类中的特殊Bean
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. 实例化所有非懒加载的单例Bean
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新,发布事件
finishRefresh();
}
}容器启动的核心逻辑是:先扫描配置生成BeanDefinition,再注册BeanPostProcessor提供扩展点,最后实例化所有非懒加载的单例Bean。
循环依赖是指A依赖B、B依赖A的情况。Spring通过三级缓存巧妙解决了这一问题:
singletonObjects:存放完全创建好的单例BeanearlySingletonObjects:存放已完成实例化但未完成属性注入的对象singletonFactories:存放提前暴露的单例工厂public class DefaultSingletonBeanRegistry {
// 一级缓存:单例池
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存:早期单例对象
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
// 三级缓存:单例工厂
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 先从一级缓存获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 从二级缓存获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// 从三级缓存获取ObjectFactory并创建早期对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 升级到二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
// 移除三级缓存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
}三级缓存解决循环依赖的核心逻辑是:当A创建时,先将A的ObjectFactory放入三级缓存,然后A进行属性注入时发现依赖B,于是去创建B;B创建时发现依赖A,从三级缓存获取A的ObjectFactory创建A的早期引用并注入B;B完成创建后,A再从缓存获取已完成的B完成注入。
Spring AOP基于动态代理实现,分为JDK动态代理和CGLIB代理两种方式:
AOP的核心在ProxyFactory类,它负责创建代理对象,构建拦截器链,每个通知(Advice)被转换为方法拦截器(MethodInterceptor)。
// Spring AOP代理创建的核心逻辑(简化)
public class ProxyFactory {
private Object target;
private List<Advice> advices;
public Object getProxy() {
// 判断使用哪种代理方式
if (hasInterfaces(target)) {
return createJdkProxy();
} else {
return createCglibProxy();
}
}
private Object createJdkProxy() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 构建拦截器链
List<MethodInterceptor> interceptors = getInterceptors(method);
// 责任链模式执行
return new ReflectiveMethodInvocation(target, method, args, interceptors).proceed();
}
}
);
}
}Pointcut表达式解析是另一个关键实现细节。Spring使用AspectJ的表达式语法,但实现了自己的解析逻辑,在匹配方法时会考虑方法的修饰符、返回类型、方法名、参数类型等因素。
理解了源码设计,我们可以手写一个精简版IoC容器,核心功能包括:包扫描、Bean实例化、依赖注入。
/**
* 自定义注解 - 标记需要被容器管理的类
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value() default "";
}
/**
* 自定义注解 - 依赖注入
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
/**
* 简易IoC容器
*/
public class SimpleApplicationContext {
// 单例池(一级缓存)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
// Bean定义映射
private final Map<String, BeanDefinition> beanDefinitions = new ConcurrentHashMap<>();
// 正在创建的Bean集合(用于检测循环依赖)
private final Set<String> singletonsCurrentlyInCreation = new HashSet<>();
private String basePackage;
public SimpleApplicationContext(String basePackage) {
this.basePackage = basePackage;
refresh();
}
/**
* 容器刷新 - 核心方法
*/
public void refresh() {
// 1. 扫描包路径,加载所有带@Component注解的类
scanPackage(basePackage);
// 2. 实例化所有非懒加载的单例Bean
for (String beanName : beanDefinitions.keySet()) {
BeanDefinition bd = beanDefinitions.get(beanName);
if (bd.isSingleton() && !bd.isLazyInit()) {
getBean(beanName);
}
}
}
/**
* 扫描包路径
*/
private void scanPackage(String packageName) {
String path = packageName.replace('.', '/');
URL url = Thread.currentThread().getContextClassLoader().getResource(path);
if (url == null) return;
File dir = new File(url.getFile());
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
scanPackage(packageName + "." + file.getName());
} else if (file.getName().endsWith(".class")) {
String className = packageName + "." + file.getName().replace(".class", "");
try {
Class<?> clazz = Class.forName(className);
if (clazz.isAnnotationPresent(Component.class)) {
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value().isEmpty() ?
decapitalize(clazz.getSimpleName()) : component.value();
BeanDefinition bd = new BeanDefinition();
bd.setBeanClass(clazz);
bd.setSingleton(true);
beanDefinitions.put(beanName, bd);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
/**
* 获取Bean - 核心方法(支持循环依赖)
*/
public Object getBean(String beanName) {
// 1. 从一级缓存获取
Object singleton = singletonObjects.get(beanName);
if (singleton != null) {
return singleton;
}
// 2. 检测循环依赖
if (singletonsCurrentlyInCreation.contains(beanName)) {
// 正在创建中,直接返回null(实际Spring会从二级缓存获取早期引用)
return null;
}
// 3. 创建Bean
BeanDefinition bd = beanDefinitions.get(beanName);
if (bd == null) {
throw new RuntimeException("Bean not found: " + beanName);
}
// 标记正在创建
singletonsCurrentlyInCreation.add(beanName);
try {
// 3.1 实例化
Object bean = bd.getBeanClass().getDeclaredConstructor().newInstance();
// 3.2 提前暴露(解决循环依赖)
singletonObjects.put(beanName, bean);
// 3.3 依赖注入
injectDependencies(bean);
// 3.4 初始化(执行@PostConstruct等)
initializeBean(bean, beanName);
// 移除正在创建标记
singletonsCurrentlyInCreation.remove(beanName);
return bean;
} catch (Exception e) {
throw new RuntimeException("Failed to create bean: " + beanName, e);
}
}
/**
* 依赖注入 - 通过反射注入@Autowired字段
*/
private void injectDependencies(Object bean) throws Exception {
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
String fieldName = field.getName();
Object dependency = getBean(fieldName);
if (dependency == null) {
// 尝试按类型注入
dependency = getBeanByType(field.getType());
}
field.set(bean, dependency);
}
}
}
private Object getBeanByType(Class<?> type) {
for (Map.Entry<String, BeanDefinition> entry : beanDefinitions.entrySet()) {
if (type.isAssignableFrom(entry.getValue().getBeanClass())) {
return getBean(entry.getKey());
}
}
return null;
}
private void initializeBean(Object bean, String beanName) throws Exception {
// 执行初始化方法
Method[] methods = bean.getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(PostConstruct.class)) {
method.setAccessible(true);
method.invoke(bean);
}
}
}
/**
* Bean定义 - 简化版
*/
public static class BeanDefinition {
private Class<?> beanClass;
private boolean singleton = true;
private boolean lazyInit = false;
// getter/setter...
}
}AOP的底层实现完全依赖BeanPostProcessor机制。通过实现BeanPostProcessor,可以在Bean初始化前后进行拦截处理。
/**
* Bean后置处理器接口
*/
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
/**
* 自定义切面注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
}
/**
* 通知类型注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Around {
String value() default "";
}
/**
* AOP后置处理器 - 核心实现
*/
public class AspectBeanPostProcessor implements BeanPostProcessor {
private List<AspectInfo> aspects = new ArrayList<>();
public AspectBeanPostProcessor(String basePackage) {
// 扫描所有带@Aspect注解的类
scanAspects(basePackage);
}
private void scanAspects(String packageName) {
// 包扫描逻辑,找到所有@Aspect类
// 解析@Around等注解,封装为AspectInfo
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 判断是否需要生成代理
for (AspectInfo aspect : aspects) {
if (aspect.match(bean.getClass())) {
return createProxy(bean, aspect);
}
}
return bean;
}
/**
* 创建代理对象
*/
private Object createProxy(Object target, AspectInfo aspect) {
Class<?> targetClass = target.getClass();
// 判断使用JDK代理还是CGLIB
if (targetClass.getInterfaces().length > 0) {
return Proxy.newProxyInstance(
targetClass.getClassLoader(),
targetClass.getInterfaces(),
new AspectInvocationHandler(target, aspect)
);
} else {
// CGLIB代理(使用Enhancer)
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(new AspectMethodInterceptor(target, aspect));
return enhancer.create();
}
}
/**
* JDK动态代理处理器
*/
private static class AspectInvocationHandler implements InvocationHandler {
private Object target;
private AspectInfo aspect;
public AspectInvocationHandler(Object target, AspectInfo aspect) {
this.target = target;
this.aspect = aspect;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 检查是否需要拦截
if (!aspect.matchMethod(method)) {
return method.invoke(target, args);
}
// 执行前置通知
aspect.before(method, args);
try {
// 执行目标方法
Object result = method.invoke(target, args);
// 执行后置通知
aspect.after(method, args, result);
return result;
} catch (Exception e) {
// 执行异常通知
aspect.afterThrowing(method, args, e);
throw e;
}
}
}
/**
* 切面信息封装
*/
private static class AspectInfo {
private Class<?> aspectClass;
private Object aspectInstance;
private String pointcut;
private Method aroundMethod;
public boolean match(Class<?> targetClass) {
// 使用正则或AspectJ表达式匹配
// 简化实现:检查类名是否包含特定模式
return targetClass.getName().contains(pointcut.replace("*", ""));
}
public boolean matchMethod(Method method) {
// 简化的方法匹配
return true;
}
public void before(Method method, Object[] args) {
// 执行@Before逻辑
}
public void after(Method method, Object[] args, Object result) {
// 执行@After逻辑
}
public void afterThrowing(Method method, Object[] args, Exception e) {
// 执行@AfterThrowing逻辑
}
}
}将AspectBeanPostProcessor注册到容器后,每个Bean在初始化完成后都会经过postProcessAfterInitialization方法检查,如果需要AOP增强则返回代理对象,否则返回原对象。
通过源码解析到手写实现,我们可以清晰地看到Spring框架的设计精髓:
掌握这些核心原理后,再看Spring源码时会产生“庖丁解牛”般的快感。当遇到@Transactional失效、循环依赖报错等问题时,不再是盲目搜索,而是能快速定位问题根源。这正是一个Java高手从“会用”到“懂原理”的质变。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。