您的位置:首页 > 汽车 > 时评 > 软件开发常用架构_营销网站制作哪家有名_百度推广seo怎么学_网推什么平台好用

软件开发常用架构_营销网站制作哪家有名_百度推广seo怎么学_网推什么平台好用

2025/5/30 3:13:27 来源:https://blog.csdn.net/qq_62729660/article/details/146563885  浏览:    关键词:软件开发常用架构_营销网站制作哪家有名_百度推广seo怎么学_网推什么平台好用
软件开发常用架构_营销网站制作哪家有名_百度推广seo怎么学_网推什么平台好用

Spring Bean的作用域

一、核心定义

  • 原型作用域(Prototype Scope)
    每次从Spring容器中请求该Bean时(例如通过getBean()方法或依赖注入),容器都会创建一个新的实例
  • 默认作用域是单例(singleton)(整个应用共享一个实例),而原型作用域的Bean是“按需生产”的独立对象。

二、原型作用域 VS 单例作用域

特性原型作用域(prototype)单例作用域(singleton)
实例数量每次请求生成新实例整个容器内仅一个共享实例
生命周期管理容器不管理销毁阶段(需手动清理资源)容器负责初始化和销毁
适用场景有状态的、需要隔离的Bean无状态的、线程安全的服务类
内存占用可能较高(频繁创建实例)较低(复用实例)

三、典型应用场景

1. 需要隔离状态的Bean
  • 示例:购物车(每个用户需要一个独立实例)
@Component
@Scope("prototype")  // 关键注解
public class ShoppingCart {private List<String> items = new ArrayList<>();public void addItem(String item) {items.add(item);}
}
  • 若用单例作用域,所有用户会共享同一个购物车,导致数据混乱。
2. 线程不安全的对象
  • 示例:数据库连接(每个线程需要独立连接)
<!-- XML配置示例 -->
<bean id="dbConnection" class="com.example.DatabaseConnection" scope="prototype"/>
3. 需要动态配置的Bean
  • 示例:每次请求根据参数生成不同配置的实例
// 通过ApplicationContext获取新实例
ApplicationContext context = ...;
ReportGenerator report = context.getBean(ReportGenerator.class);

四、配置方式

1. 注解方式
  • 使用@Scope注解指定作用域:
@Component
@Scope("prototype")  // 或 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class MyPrototypeBean { ... }
2. XML配置
  • 在Bean定义中添加scope属性:
<bean id="myBean" class="com.example.MyBean" scope="prototype"/>

五、生命周期特点

  • 初始化:每次创建实例时调用@PostConstruct方法(如果有)。
  • 销毁:容器不会调用原型Bean的@PreDestroy方法!
    • 原因:容器不跟踪原型Bean的生命周期,需自行释放资源(如关闭文件句柄、数据库连接)。

六、注意事项

  1. 性能影响

    • 频繁创建原型Bean可能增加内存和GC压力,需权衡是否真需要多实例。
  2. 与单例Bean的依赖关系

    • 若单例Bean依赖原型Bean,直接注入会导致原型Bean仅初始化一次(与预期不符)。
    • 解决方案:通过ObjectFactoryProvider延迟获取:
@Autowired
private ObjectFactory<PrototypeBean> prototypeBeanFactory;public void usePrototype() {PrototypeBean bean = prototypeBeanFactory.getObject();
}

      3. 与线程安全问题

  • 原型作用域本身不保证线程安全,需结合其他机制(如ThreadLocal)控制。

七、代码验证示例

@SpringBootTest
public class PrototypeTest {@Autowiredprivate ApplicationContext context;@Testpublic void testPrototypeScope() {// 两次获取Bean实例Object bean1 = context.getBean("myPrototypeBean");Object bean2 = context.getBean("myPrototypeBean");// 断言两个实例不同Assert.assertNotSame(bean1, bean2);  // 测试通过}
}

总结

  • 原型作用域的核心:按需生成新实例,适用于有状态对象需要隔离的场景。
  • 慎用场景:避免在无状态服务或高频请求中使用,防止资源浪费。
  • 生命周期责任:开发者需自行管理原型Bean的资源释放。

Spring 循环依赖

一、循环依赖解决:三级缓存机制

Spring 通过三级缓存解决单例 Bean 的循环依赖问题。三级缓存分别为:

  1. singletonObjects(一级缓存):存储完全初始化后的单例 Bean。
  2. earlySingletonObjects(二级缓存):存储已实例化但未完成属性注入的早期 Bean 引用。
  3. singletonFactories(三级缓存):存储 Bean 的 ObjectFactory,用于生成早期对象(可能包含代理对象)。

解决流程示例(Bean A 依赖 Bean B,Bean B 依赖 Bean A):

  1. 实例化 Bean A,将其 ObjectFactory 放入 singletonFactories
  2. 填充 A 的属性时,发现依赖 B,触发 B 的实例化。
  3. 实例化 Bean B,将其 ObjectFactory 放入 singletonFactories
  4. 填充 B 的属性时,发现依赖 A,从 singletonFactories 获取 A 的 ObjectFactory,生成早期引用并放入 earlySingletonObjects
  5. B 完成初始化,移入 singletonObjects
  6. A 获取 B 的实例后完成初始化,移入 singletonObjects

关键点

  • 仅单例 Bean 适用,原型(prototype)作用域会直接报错。
  • 若存在 AOP 代理,三级缓存通过 ObjectFactory 提前生成代理对象,确保依赖注入正确。

Spring事务传播机制

一、事务传播机制

Spring 定义了多种事务传播行为,核心类型如下:

  1. PROPAGATION_REQUIRED(默认)

    • 若当前存在事务,则加入该事务;否则新建事务。
    • 示例:方法 A 调用方法 B,若 A 已开启事务,B 加入同一事务;若 A 无事务,B 新建事务。
  2. PROPAGATION_REQUIRES_NEW

    • 无论当前是否存在事务,始终新建事务,并挂起当前事务(若存在)。
    • 示例:方法 A(事务 T1)调用方法 B(REQUIRES_NEW),B 开启新事务 T2,T1 被挂起。T2 提交后,T1 继续执行。

对比

传播类型事务独立性回滚影响
PROPAGATION_REQUIRED共享同一事务任一操作失败,整体回滚
PROPAGATION_REQUIRES_NEW独立事务,外部事务挂起内部事务回滚不影响外部,反之亦然

二、事务失效的常见场景

1. 非 public 方法

  • 原因:Spring 基于代理实现事务,无法为 private 或 protected 方法生成代理。
  • 解决:确保事务方法为 public

2. 同类内调用

  • 原因:通过 this 调用本类方法,未经过代理对象,事务拦截失效。
  • 示例
@Service
public class UserService {public void methodA() {this.methodB(); // 直接调用,事务失效}@Transactionalpublic void methodB() { ... }
}
  • 解决:使用 @Autowired 注入自身代理或通过 AopContext.currentProxy() 调用。

3. 异常被捕获未抛出

  • 原因:Spring 默认在抛出未检查异常(如 RuntimeException)时回滚。若异常被捕获且未重新抛出,事务不生效。
  • 示例
@Transactional
public void update() {try {// 数据库操作} catch (Exception e) {// 捕获异常未抛出 → 事务未回滚}
}
  • 解决:抛出异常或设置 @Transactional(rollbackFor = Exception.class)

总结

  • 循环依赖:三级缓存通过提前暴露 Bean 的早期引用,结合代理机制解决单例 Bean 循环依赖。
  • 事务传播:根据业务需求选择传播行为,注意 PROPAGATION_REQUIRES_NEW 的事务独立性。
  • 事务失效:避免非 public 方法、同类内直接调用及异常捕获不处理,确保事务正确生效。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com