在传统Java开发中,对象创建和依赖管理通常采用硬编码方式:
java复制// 传统方式 - 紧耦合
public class OrderService {
private UserRepository userRepo = new UserRepositoryImpl();
private PaymentService paymentService = new PaymentServiceImpl();
public void createOrder() {
userRepo.findUser();
paymentService.processPayment();
}
}
这种方式的痛点在于:
Spring IoC 通过控制反转解决了这些问题:
java复制// IoC方式 - 松耦合
public class OrderService {
private final UserRepository userRepo;
private final PaymentService paymentService;
// 构造器注入
public OrderService(UserRepository userRepo,
PaymentService paymentService) {
this.userRepo = userRepo;
this.paymentService = paymentService;
}
}
Spring IoC 容器的核心是 BeanFactory 接口体系,其关键实现包括:
java复制public interface BeanFactory {
Object getBean(String name);
<T> T getBean(Class<T> requiredType);
boolean containsBean(String name);
// ...
}
容器启动时的关键步骤:
配置元数据加载:
ClassPathXmlApplicationContextAnnotationConfigApplicationContext@Configuration 类BeanDefinition 解析:
BeanDefinition 对象依赖注入处理:
使用 @Conditional 实现条件化Bean创建:
java复制@Configuration
public class DataSourceConfig {
@Bean
@Conditional(ProdEnvCondition.class)
public DataSource prodDataSource() {
return new HikariDataSource();
}
@Bean
@Conditional(DevEnvCondition.class)
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder().build();
}
}
public class ProdEnvCondition implements Condition {
@Override
public boolean matches(ConditionContext context,
AnnotatedTypeMetadata metadata) {
return "prod".equals(context.getEnvironment().getProperty("env"));
}
}
Spring 提供了多个扩展点干预Bean生命周期:
java复制public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
// 初始化前处理
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 初始化后处理
if (bean instanceof MyService) {
return Proxy.newProxyInstance(...); // AOP代理
}
return bean;
}
}
public class CustomBeanFactoryPostProcessor
implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 可以修改BeanDefinition
}
}
Spring Bean 的生命周期包含以下关键阶段:
实例化阶段:
属性赋值阶段:
BeanPostProcessor 的 postProcessProperties初始化阶段:
@PostConstruct 注解方法InitializingBean 接口的 afterPropertiesSet()init-method使用阶段:
销毁阶段:
@PreDestroy 注解方法DisposableBean 接口的 destroy()destroy-method不同作用域的Bean有不同的线程安全考虑:
| 作用域 | 线程安全策略 | 适用场景 |
|---|---|---|
| singleton | 无状态或线程安全实现 | Service、Repository |
| prototype | 每次请求新实例 | 有状态对象 |
| request | 每个HTTP请求独立实例 | Web请求相关数据 |
| session | 每个用户会话独立实例 | 用户会话数据 |
| application | ServletContext级别单例 | 全局共享数据 |
java复制@Service
@Scope(value = WebApplicationContext.SCOPE_REQUEST,
proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserPreferences {
// 每个HTTP请求独立实例
}
Spring 通过三级缓存解决setter注入的循环依赖:
java复制// 三级缓存结构
public class DefaultSingletonBeanRegistry {
// 一级缓存:完整Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
// 二级缓存:早期引用
private final Map<String, Object> earlySingletonObjects = new HashMap<>();
// 三级缓存:ObjectFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();
}
解决流程示例(A依赖B,B依赖A):
注意:构造器注入的循环依赖无法解决,因为对象实例化前无法提前暴露引用。
Spring AOP 的核心组件包括:
Spring 通过 AbstractAutoProxyCreator 创建代理:
java复制public abstract class AbstractAutoProxyCreator
extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean != null) {
// 检查是否需要代理
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 1. 检查是否已处理
// 2. 检查是否是基础设施类
// 3. 检查是否应该跳过
// 获取适用的通知
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(...);
if (specificInterceptors != DO_NOT_PROXY) {
// 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
return proxy;
}
return bean;
}
}
| 特性 | JDK 动态代理 | CGLIB 代理 |
|---|---|---|
| 代理方式 | 基于接口 | 基于继承 |
| 性能 | 反射调用,较慢 | 字节码生成,较快 |
| 限制 | 目标类必须实现接口 | 不能代理final类/方法 |
| 创建方式 | Proxy.newProxyInstance() | Enhancer.create() |
| Spring默认选择 | 目标有接口时 | 目标无接口或proxyTargetClass=true |
java复制// 强制使用CGLIB代理
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Configuration
public class AppConfig {
// ...
}
最常见的代理失效场景:
java复制@Service
public class OrderService {
@Transactional
public void placeOrder(Order order) {
// 直接内部调用导致事务失效
validateOrder(order);
// ...
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void validateOrder(Order order) {
// 这个事务不会生效
}
}
解决方案对比:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 自我注入 | 简单直接 | 可能引起循环依赖 |
| ApplicationContext | 灵活 | 引入容器依赖 |
| AopContext | 最优雅的方案 | 需要配置exposeProxy |
推荐方案:
java复制@EnableAspectJAutoProxy(exposeProxy = true)
@SpringBootApplication
public class App { ... }
@Service
public class OrderService {
@Transactional
public void placeOrder(Order order) {
// 通过AopContext获取当前代理
((OrderService)AopContext.currentProxy()).validateOrder(order);
}
}
java复制@Service
public class UserService {
@Cacheable("users")
public final User getUser(Long id) { // 缓存失效
return repository.findById(id);
}
}
原因:CGLIB 通过生成子类实现代理,无法重写final方法。
java复制@Service
public class LogService {
@Async
private void writeLog(String message) { // 异步失效
// 不会异步执行
}
}
原因:代理对象无法拦截private方法的调用。
java复制public class Test {
public static void main(String[] args) {
// 直接new的对象不受Spring管理
UserService service = new UserServiceImpl();
service.doSomething(); // AOP完全失效
}
}
正确做法:始终通过Spring容器获取Bean:
java复制@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testService() {
userService.doSomething(); // AOP生效
}
}
创建自定义事务注解:
java复制@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(
isolation = Isolation.READ_COMMITTED,
propagation = Propagation.REQUIRED,
timeout = 30
)
public @interface AppTransaction {
String value() default "";
}
使用方式:
java复制@Service
public class PaymentService {
@AppTransaction
public void processPayment(Payment payment) {
// 带有自定义事务配置
}
}
within() 限定包路径@annotation 精确匹配java复制@Pointcut("within(com.example.service..*) && " +
"@annotation(com.example.annotation.Auditable)")
public void auditableServiceMethod() {}
代理选择策略:
proxyTargetClass 配置缓存代理对象:
AopContext.currentProxy()@EnableTransactionManagement不同传播行为的实际表现:
java复制@Service
public class OrderService {
@Autowired
private InventoryService inventoryService;
@Transactional
public void placeOrder(Order order) {
// 方法1:REQUIRED
inventoryService.updateStock(order);
// 方法2:REQUIRES_NEW
inventoryService.logInventoryChange(order);
}
}
@Service
public class InventoryService {
@Transactional(propagation = Propagation.REQUIRED)
public void updateStock(Order order) {
// 加入外部事务
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logInventoryChange(Order order) {
// 新启独立事务
}
}
使用 AbstractRoutingDataSource 实现动态数据源:
java复制public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDataSourceType();
}
}
@Configuration
public class DataSourceConfig {
@Bean
@Primary
public DataSource dynamicDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("master", masterDataSource());
targetDataSources.put("slave", slaveDataSource());
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources);
dataSource.setDefaultTargetDataSource(masterDataSource());
return dataSource;
}
}
// 使用注解切换数据源
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String value() default "master";
}
实现方法级权限控制:
java复制@Aspect
@Component
public class PermissionAspect {
@Autowired
private AuthService authService;
@Pointcut("@annotation(com.example.annotation.RequirePermission)")
public void permissionCheck() {}
@Around("permissionCheck()")
public Object checkPermission(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
RequirePermission annotation = method.getAnnotation(RequirePermission.class);
if (!authService.hasPermission(annotation.value())) {
throw new AccessDeniedException("Permission denied");
}
return pjp.proceed();
}
}
// 使用示例
@RestController
public class UserController {
@RequirePermission("user:delete")
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
// 需要user:delete权限
}
}
减少代理层级:
切点表达式优化:
execution() 而非 within()缓存切点匹配结果:
AspectJExpressionPointcut 的静态切点代理类型检查:
java复制@Autowired
private MyService myService;
public void checkProxyType() {
boolean isJdkProxy = AopUtils.isJdkDynamicProxy(myService);
boolean isCglibProxy = AopUtils.isCglibProxy(myService);
// ...
}
事务状态监控:
java复制TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.isActualTransactionActive();
AOP调用链分析:
Spring 生命周期中的模板方法:
java复制public abstract class AbstractBeanFactory {
protected Object initializeBean(String beanName, Object bean,
RootBeanDefinition mbd) {
// 1. Aware接口回调
invokeAwareMethods(beanName, bean);
// 2. BeanPostProcessor前置处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
try {
// 3. 初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
throw new BeanCreationException(...);
}
// 4. BeanPostProcessor后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
}
Spring 事件发布与监听:
java复制// 自定义事件
public class OrderCreatedEvent extends ApplicationEvent {
public OrderCreatedEvent(Order source) {
super(source);
}
}
// 事件发布
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Transactional
public void createOrder(Order order) {
// 保存订单
eventPublisher.publishEvent(new OrderCreatedEvent(order));
}
}
// 事件监听
@Component
public class OrderEventListener {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
// 处理订单创建事件
}
}
AbstractApplicationContext.refresh() 关键步骤:
prepareRefresh():初始化启动时间戳、活跃状态标志obtainFreshBeanFactory():创建/刷新BeanFactoryprepareBeanFactory():配置标准BeanFactory特性postProcessBeanFactory():执行BeanFactory后置处理器invokeBeanFactoryPostProcessors():处理 BeanDefinitionRegistryPostProcessorregisterBeanPostProcessors():注册Bean后置处理器initMessageSource():初始化国际化资源initApplicationEventMulticaster():初始化事件广播器onRefresh():模板方法,子类扩展registerListeners():注册监听器finishBeanFactoryInitialization():初始化所有单例BeanfinishRefresh():发布ContextRefreshedEventAbstractAutoProxyCreator.createProxy() 关键步骤:
ProxyFactory 实例Advisor(包含Pointcut和Advice)ProxyFactory.getProxy() 创建代理对象
JdkDynamicAopProxyObjenesisCglibAopProxy问题现象:
java复制@Component
public class MyService { ... }
@Configuration
public class MyConfig {
@Bean
public MyService myService() { ... } // 名称冲突
}
解决方案:
java复制@Component("componentMyService")
public class MyService { ... }
@Bean("configMyService")
public MyService myService() { ... }
@Primary 标记优先Bean问题现象:
java复制@RestController
@SessionScope
public class UserPreferenceController implements Serializable {
// CGLIB代理对象序列化失败
}
解决方案:
Serializable 接口java复制public interface UserPreferenceService {
void updatePreferences(UserPref pref);
}
@Service
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public class UserPreferenceServiceImpl implements UserPreferenceService {
// ...
}
错误用法:
java复制@Service
public class OrderService {
@Transactional(timeout = 10)
public void processBatchOrders(List<Order> orders) {
for (Order order : orders) {
processSingleOrder(order); // 每个子方法都会重置超时
}
}
@Transactional(timeout = 30)
public void processSingleOrder(Order order) {
// 实际超时是30秒而非10秒
}
}
正确做法:
java复制@Transactional(timeout = 10)
public void processBatchOrders(List<Order> orders) {
orders.forEach(order -> {
// 在同一个事务中处理
processOrderInternal(order);
});
}
AOT(Ahead-Of-Time)编译支持:
GraalVM 原生镜像支持:
JDK 17+ 特性集成:
自动配置优化:
性能增强:
观测性增强:
依赖注入原则:
Bean作用域选择:
生命周期管理:
@PostConstruct 和 @PreDestroy切面设计原则:
性能优化建议:
事务管理规范:
| 场景 | 推荐代理方式 | 配置方式 |
|---|---|---|
| 接口明确的Service层 | JDK动态代理 | 默认行为 |
| 没有接口的类 | CGLIB | @EnableAspectJAutoProxy(proxyTargetClass=true) |
| 需要序列化的场景 | 接口代理 | @Scope(proxyMode=ScopedProxyMode.INTERFACES) |
| 性能敏感场景 | 编译时织入(AspectJ) | 使用AspectJ Maven插件 |
场景:ServiceA 依赖 ServiceB,ServiceB 又依赖 ServiceA
解决方案:
重构设计(推荐):
Setter注入:
java复制@Service
public class ServiceA {
private ServiceB serviceB;
@Autowired
public void setServiceB(ServiceB serviceB) {
this.serviceB = serviceB;
}
}
@Lazy 注解:
java复制@Service
public class ServiceA {
@Autowired
@Lazy
private ServiceB serviceB;
}
解决方案:
AbstractRoutingDataSource:
java复制public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return TransactionContext.getCurrentDataSource();
}
}
ChainedTransactionManager:
java复制@Bean
public PlatformTransactionManager transactionManager() {
return new ChainedTransactionManager(
new JpaTransactionManager(entityManagerFactory1),
new JpaTransactionManager(entityManagerFactory2)
);
}
JTA 全局事务:
java复制@Bean
public JtaTransactionManager transactionManager() {
return new JtaTransactionManager();
}
问题:应用启动时大量动态代理创建导致启动慢
解决方案:
延迟初始化:
java复制@Lazy
@Service
public class MyService { ... }
使用AspectJ编译时织入:
xml复制<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<complianceLevel>11</complianceLevel>
<source>11</source>
<target>11</target>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
</plugin>
缓存代理对象:
java复制@Service
public class MyService {
@Autowired
private ApplicationContext context;
private MyService proxy;
@PostConstruct
public void init() {
this.proxy = context.getBean(MyService.class);
}
}
优化建议:
合理设置事务隔离级别:
控制事务粒度:
批量操作优化:
java复制@Transactional
public void batchInsert(List<Entity> entities) {
for (Entity entity : entities) {
entityManager.persist(entity);
if (i % 50 == 0) {
entityManager.flush();
entityManager.clear();
}
}
}
查看代理类型:
java复制AopUtils.isJdkDynamicProxy(bean);
AopUtils.isCglibProxy(bean);
获取目标类:
java复制AopProxyUtils.ultimateTargetClass(bean);
Spring Boot Actuator:
/beans 端点查看Bean信息/mappings 查看控制器映射事务同步管理器:
java复制TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.isActualTransactionActive();
自定义事务监听器:
java复制@TransactionalEventListener
public void handleTransactionEvent(TransactionPhaseEvent event) {
// 处理事务事件
}
Micrometer 指标:
spring.transaction 指标组Spring WebFlux 中的AOP特性:
java复制@Aspect
@Component
public class ReactiveLoggingAspect {
@Around("@annotation(Loggable)")
public Mono<?> logReactiveMethod(ProceedingJoinPoint pjp) {
return Mono.defer(() -> {
long start = System.currentTimeMillis();
return ((Mono<?>) pjp.proceed())
.doOnSuccess(v -> logDuration(pjp, start, true))
.doOnError(e -> logDuration(pjp, start, false));
});
}
}
Serverless 环境适配:
Service Mesh 集成:
Kubernetes 原生特性:
在实际项目开发中,正确理解Spring IoC和AOP的工作原理至关重要。以下是我总结的几点关键经验:
代理失效问题:遇到AOP不生效时,首先检查是否是内部调用问题,这是最常见的陷阱。我习惯在项目启动时就配置 @EnableAspectJAutoProxy(exposeProxy = true) 以备不时之需。
事务管理:对于复杂业务逻辑,我倾向于使用显式的编程式事务管理(TransactionTemplate)而非声明式事务,这样可以更精确地控制事务边界。
性能考量:在高并发场景下,我会特别关注切点表达式的性能,避免使用过于宽泛的匹配规则。对于性能关键路径,有时会牺牲一些AOP的优雅性来换取更好的性能。
测试策略:对于AOP增强的组件,集成测试至关重要。我通常会编写专门的测试用例来验证代理行为是否符合预期,特别是在涉及事务传播行为的场景。
设计原则:虽然Spring提供了强大的AOP能力,但我始终坚持"显式优于隐式"的原则,避免过度使用AOP导致代码难以理解和维护。
Spring框架的IoC和AOP机制看似简单,但要真正掌握其精髓并灵活运用,需要大量的实践和不断的总结。希望这些经验分享能帮助开发者更好地运用这些强大的特性。