Spring框架原理深度解析

概述

Spring框架是Java企业级开发的核心框架,深入理解其原理是高级开发工程师的必备技能。本文涵盖IoC容器、AOP机制、SpringBoot自动配置等核心面试内容。

核心面试问题

1. IoC容器核心原理

面试问题:Spring IoC容器的实现原理,Bean的生命周期是怎样的?

IoC容器架构

// 自定义简化版IoC容器实现
public class SimpleIoCContainer {
    private final Map<String, Object> beanDefinitionMap = new ConcurrentHashMap<>();
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();

    // 注册Bean定义
    public void registerBeanDefinition(String beanName, Class<?> beanClass) {
        beanDefinitionMap.put(beanName, beanClass);
    }

    // 获取Bean实例
    @SuppressWarnings("unchecked")
    public <T> T getBean(String beanName, Class<T> requiredType) {
        // 先从单例池中获取
        Object bean = singletonObjects.get(beanName);
        if (bean != null) {
            return (T) bean;
        }

        // 创建新的Bean实例
        Class<?> beanClass = (Class<?>) beanDefinitionMap.get(beanName);
        if (beanClass == null) {
            throw new RuntimeException("No bean definition found for: " + beanName);
        }

        try {
            // 实例化
            Object instance = beanClass.getDeclaredConstructor().newInstance();

            // 依赖注入
            performDependencyInjection(instance);

            // 初始化回调
            if (instance instanceof InitializingBean) {
                ((InitializingBean) instance).afterPropertiesSet();
            }

            // 放入单例池
            singletonObjects.put(beanName, instance);

            return (T) instance;
        } catch (Exception e) {
            throw new RuntimeException("Failed to create bean: " + beanName, e);
        }
    }

    private void performDependencyInjection(Object instance) throws IllegalAccessException {
        Field[] fields = instance.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                String dependencyName = field.getType().getSimpleName().toLowerCase();
                Object dependency = getBean(dependencyName, field.getType());
                field.set(instance, dependency);
            }
        }
    }

    // 简化的注解
    @interface Autowired {}
    interface InitializingBean {
        void afterPropertiesSet() throws Exception;
    }
}

Bean生命周期详解

@Component
public class LifecycleBean implements BeanNameAware, BeanFactoryAware, 
    ApplicationContextAware, InitializingBean, DisposableBean {

    private String beanName;
    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;

    // 1. 构造器
    public LifecycleBean() {
        System.out.println("1. 构造器调用");
    }

    // 2. 属性注入
    @Autowired
    private SomeService someService;

    // 3. Aware接口回调
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("3. BeanNameAware.setBeanName: " + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
        System.out.println("4. BeanFactoryAware.setBeanFactory");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("5. ApplicationContextAware.setApplicationContext");
    }

    // 6. BeanPostProcessor前置处理
    // 7. @PostConstruct注解方法
    @PostConstruct
    public void postConstruct() {
        System.out.println("7. @PostConstruct注解方法");
    }

    // 8. InitializingBean.afterPropertiesSet
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("8. InitializingBean.afterPropertiesSet");
    }

    // 9. init-method指定的方法
    public void initMethod() {
        System.out.println("9. init-method指定的方法");
    }

    // 10. BeanPostProcessor后置处理

    // Bean销毁阶段
    @PreDestroy
    public void preDestroy() {
        System.out.println("销毁前: @PreDestroy注解方法");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("销毁中: DisposableBean.destroy");
    }

    public void destroyMethod() {
        System.out.println("销毁中: destroy-method指定的方法");
    }
}

// 自定义BeanPostProcessor
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof LifecycleBean) {
            System.out.println("6. BeanPostProcessor前置处理: " + beanName);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof LifecycleBean) {
            System.out.println("10. BeanPostProcessor后置处理: " + beanName);
        }
        return bean;
    }
}

2. AOP切面编程原理

面试问题:Spring AOP的实现原理,JDK动态代理与CGLIB的区别?

AOP核心概念实现

// 自定义切面注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecution {
    String value() default "";
}

// 切面定义
@Aspect
@Component
public class LoggingAspect {

    // 切点表达式
    @Pointcut("@annotation(LogExecution)")
    public void logExecutionPointcut() {}

    // 前置通知
    @Before("logExecutionPointcut() && @annotation(logExecution)")
    public void beforeExecution(JoinPoint joinPoint, LogExecution logExecution) {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        System.out.println("开始执行: " + className + "." + methodName + 
                          " - " + logExecution.value());
    }

    // 环绕通知
    @Around("logExecutionPointcut()")
    public Object aroundExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

        try {
            Object result = joinPoint.proceed();
            long endTime = System.currentTimeMillis();
            System.out.println("执行成功,耗时: " + (endTime - startTime) + "ms");
            return result;
        } catch (Exception e) {
            System.out.println("执行异常: " + e.getMessage());
            throw e;
        }
    }

    // 后置通知
    @AfterReturning(pointcut = "logExecutionPointcut()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("方法返回: " + result);
    }

    // 异常通知
    @AfterThrowing(pointcut = "logExecutionPointcut()", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Exception exception) {
        System.out.println("方法异常: " + exception.getMessage());
    }
}

// 业务服务类
@Service
public class UserService {

    @LogExecution("获取用户信息")
    public User getUserById(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        return new User(id, "用户" + id);
    }

    @LogExecution("保存用户")
    public User saveUser(User user) {
        // 模拟保存操作
        user.setId(System.currentTimeMillis());
        return user;
    }
}

动态代理原理实现

// JDK动态代理实现
public class JdkProxyFactory {

    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target, InvocationHandler handler) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            handler
        );
    }
}

// 自定义InvocationHandler
public class LoggingInvocationHandler implements InvocationHandler {
    private final Object target;

    public LoggingInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK代理 - 方法调用前: " + method.getName());

        try {
            Object result = method.invoke(target, args);
            System.out.println("JDK代理 - 方法调用后: " + method.getName());
            return result;
        } catch (Exception e) {
            System.out.println("JDK代理 - 方法异常: " + e.getMessage());
            throw e;
        }
    }
}

// CGLIB代理实现
public class CglibProxyFactory {

    @SuppressWarnings("unchecked")
    public static <T> T createProxy(Class<T> targetClass) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetClass);
        enhancer.setCallback(new LoggingMethodInterceptor());
        return (T) enhancer.create();
    }
}

// CGLIB方法拦截器
public class LoggingMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("CGLIB代理 - 方法调用前: " + method.getName());

        try {
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("CGLIB代理 - 方法调用后: " + method.getName());
            return result;
        } catch (Exception e) {
            System.out.println("CGLIB代理 - 方法异常: " + e.getMessage());
            throw e;
        }
    }
}

// 代理对比测试
public class ProxyComparisonTest {

    public static void main(String[] args) {
        // JDK动态代理(需要接口)
        UserService userService = new UserServiceImpl();
        UserService jdkProxy = JdkProxyFactory.createProxy(userService, 
            new LoggingInvocationHandler(userService));
        jdkProxy.getUserById(1L);

        // CGLIB代理(不需要接口)
        UserServiceImpl cglibProxy = CglibProxyFactory.createProxy(UserServiceImpl.class);
        cglibProxy.getUserById(1L);
    }
}

3. Spring Boot自动配置原理

面试问题:Spring Boot的自动配置是如何实现的?@SpringBootApplication注解的作用?

自动配置核心机制

// @SpringBootApplication注解分析
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration  // 等同于@Configuration
@EnableAutoConfiguration  // 启用自动配置
@ComponentScan(excludeFilters = { // 组件扫描
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    // ...
}

// 自定义自动配置类
@Configuration
@ConditionalOnClass(DataSource.class)  // 当类路径存在DataSource时
@ConditionalOnMissingBean(DataSource.class)  // 当容器中没有DataSource时
@EnableConfigurationProperties(DataSourceProperties.class)  // 启用配置属性
public class CustomDataSourceAutoConfiguration {

    @Autowired
    private DataSourceProperties properties;

    @Bean
    @ConditionalOnProperty(name = "custom.datasource.enabled", havingValue = "true")
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(properties.getUrl());
        dataSource.setUsername(properties.getUsername());
        dataSource.setPassword(properties.getPassword());
        dataSource.setDriverClassName(properties.getDriverClassName());
        return dataSource;
    }
}

// 配置属性类
@ConfigurationProperties(prefix = "custom.datasource")
@Data
public class DataSourceProperties {
    private String url;
    private String username;
    private String password;
    private String driverClassName = "com.mysql.cj.jdbc.Driver";
    private boolean enabled = true;
}

// 自动配置注册
// 在META-INF/spring.factories文件中:
// org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
// com.example.CustomDataSourceAutoConfiguration

条件注解实现

// 自定义条件注解
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnRedisCondition.class)
public @interface ConditionalOnRedis {
    String[] value() default {};
}

// 条件实现类
public class OnRedisCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        try {
            // 检查Redis相关的类是否存在
            context.getClassLoader().loadClass("redis.clients.jedis.Jedis");

            // 检查配置属性
            Environment env = context.getEnvironment();
            String host = env.getProperty("redis.host");
            String port = env.getProperty("redis.port");

            return host != null && port != null;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
}

// 使用自定义条件
@Configuration
@ConditionalOnRedis
public class RedisAutoConfiguration {

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置Redis模板
        return template;
    }
}

4. Spring事务管理原理

面试问题:Spring事务的传播机制,以及@Transactional注解的实现原理?

事务传播机制

@Service
public class TransactionService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private OrderRepository orderRepository;

    // REQUIRED:默认传播行为
    @Transactional(propagation = Propagation.REQUIRED)
    public void requiredMethod() {
        userRepository.save(new User("user1"));
        // 如果当前存在事务,则加入该事务;如果不存在,则创建新事务
    }

    // REQUIRES_NEW:总是创建新事务
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void requiresNewMethod() {
        orderRepository.save(new Order("order1"));
        // 总是创建新事务,如果当前存在事务,则挂起当前事务
    }

    // NESTED:嵌套事务
    @Transactional(propagation = Propagation.NESTED)
    public void nestedMethod() {
        userRepository.save(new User("user2"));
        // 如果当前存在事务,则在嵌套事务内执行
    }

    // 事务传播示例
    @Transactional
    public void businessMethod() {
        try {
            requiredMethod();    // 加入当前事务
            requiresNewMethod(); // 创建新事务
            nestedMethod();      // 嵌套事务
        } catch (Exception e) {
            // 异常处理
            throw e;
        }
    }

    // 事务隔离级别
    @Transactional(
        isolation = Isolation.READ_COMMITTED,  // 隔离级别
        timeout = 30,                          // 超时时间
        readOnly = true,                       // 只读事务
        rollbackFor = Exception.class,         // 回滚异常
        noRollbackFor = IllegalArgumentException.class // 不回滚异常
    )
    public User getUser(Long id) {
        return userRepository.findById(id);
    }
}

事务管理器实现

// 自定义事务管理器
@Configuration
@EnableTransactionManagement
public class TransactionConfig {

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    // 编程式事务模板
    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
        return new TransactionTemplate(transactionManager);
    }
}

// 编程式事务使用
@Service
public class ProgrammaticTransactionService {

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private UserRepository userRepository;

    public User createUser(String name) {
        return transactionTemplate.execute(status -> {
            try {
                User user = new User(name);
                userRepository.save(user);

                // 模拟业务逻辑
                if (name.equals("error")) {
                    throw new RuntimeException("模拟异常");
                }

                return user;
            } catch (Exception e) {
                status.setRollbackOnly(); // 标记事务回滚
                throw e;
            }
        });
    }

    // 事务回调
    public void executeWithTransaction() {
        transactionTemplate.executeWithoutResult(status -> {
            userRepository.save(new User("test"));
            // 无返回值的事务操作
        });
    }
}

5. Spring MVC工作原理

面试问题:SpringMVC的请求处理流程,DispatcherServlet的作用?

MVC核心组件

// 自定义拦截器
@Component
public class LoggingInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("请求前处理: " + request.getRequestURI());
        return true; // 返回false会终止请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
                          Object handler, ModelAndView modelAndView) {
        System.out.println("请求后处理: " + request.getRequestURI());
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                               Object handler, Exception ex) {
        System.out.println("请求完成处理: " + request.getRequestURI());
    }
}

// 全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ErrorResponse handleIllegalArgument(IllegalArgumentException e) {
        return new ErrorResponse("参数错误", e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ErrorResponse handleGenericException(Exception e) {
        return new ErrorResponse("系统错误", e.getMessage());
    }

    // 数据绑定异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ErrorResponse handleValidationException(MethodArgumentNotValidException e) {
        StringBuilder sb = new StringBuilder();
        e.getBindingResult().getFieldErrors().forEach(error -> 
            sb.append(error.getField()).append(": ").append(error.getDefaultMessage()).append("; ")
        );
        return new ErrorResponse("验证失败", sb.toString());
    }
}

// 自定义参数解析器
public class CustomArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(CurrentUser.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
        // 从请求中解析当前用户信息
        String userId = webRequest.getHeader("User-Id");
        if (userId != null) {
            return new User(Long.parseLong(userId), "CurrentUser");
        }
        return null;
    }
}

// 配置类
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private LoggingInterceptor loggingInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loggingInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/static/**");
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new CustomArgumentResolver());
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 配置消息转换器
        converters.add(new MappingJackson2HttpMessageConverter());
    }
}

高频面试题目

1. 深度理解题目

Q: Spring如何解决循环依赖问题?

A: Spring通过三级缓存解决循环依赖:

  1. 一级缓存(singletonObjects):完整的Bean实例
  2. 二级缓存(earlySingletonObjects):早期的Bean引用
  3. 三级缓存(singletonFactories):Bean工厂

解决过程:

  • 实例化Bean A,放入三级缓存
  • 注入Bean B时,发现B依赖A
  • 从三级缓存获取A的早期引用
  • 完成B的创建,再完成A的初始化

Q: @Autowired和@Resource的区别?

A: 主要区别:

  • @Autowired:Spring注解,按类型注入,可配合@Qualifier按名称
  • @Resource:Java标准注解,按名称注入,找不到再按类型
  • 优先级:@Resource优先按名称,@Autowired优先按类型

2. 实战应用题目

Q: 如何自定义Spring Boot Starter?

答题要点:

  1. 创建自动配置类
  2. 定义配置属性类
  3. 编写spring.factories文件
  4. 使用条件注解控制配置
  5. 提供默认配置和文档

Q: Spring事务失效的场景有哪些?

常见失效场景:

  1. 方法不是public的
  2. 同类内部方法调用
  3. 异常被捕获但不重新抛出
  4. 数据库不支持事务
  5. 没有被Spring管理的对象

总结

Spring框架面试重点:

  1. IoC原理:容器实现、Bean生命周期、依赖注入
  2. AOP机制:代理实现、切面编程、通知类型
  3. 自动配置:条件注解、配置属性、启动原理
  4. 事务管理:传播机制、隔离级别、实现原理
  5. MVC架构:请求处理流程、组件作用、扩展点

建议结合实际项目经验,能够描述Spring在项目中的具体应用和遇到的问题。

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-07-28 18:05:38

results matching ""

    No results matching ""