ioc容器只管理由其创建、配置并注入依赖的bean,默认单例,生命周期受控;非容器创建的对象不参与di或aop。

IOC 容器到底管理什么对象?
Spring 的 IOC 容器不管理所有 Java 对象,只管理由它创建、配置并注入依赖的 Bean。这些 Bean 默认是单例(singleton),且生命周期受容器控制:从实例化、属性填充、初始化回调(如 @PostConstruct 或 InitializingBean.afterPropertiesSet()),到销毁前回调(如 @PreDestroy)。
常见误区是认为 new 出来的对象也能被 AOP 代理或自动注入——不会。只有容器中注册的 Bean 才参与依赖注入和切面织入。
- 使用
@Component、@Service、@Repository、@Controller等注解标记的类,在启用@ComponentScan后会被自动注册为Bean -
@Bean方法返回的对象,无论是否 new,都会被容器接管并统一管理 - 手动调用
new UserService()创建的实例,即使类型相同,也不在容器中,无法被@Autowired注入,也不会被 AOP 拦截
AOP 的代理机制为什么有时不生效?
Spring AOP 基于代理实现,而默认只对 public 方法生效;非 public 方法(private、protected、包级)无法被 JDK 动态代理或 CGLIB 正确拦截。
更隐蔽的问题是:同一个 Bean 内部方法自调用(this.methodB() 调用 @Transactional 或 @Cacheable 方法)不会触发代理逻辑,因为调用未经过代理对象,而是直接走 this 引用。
立即学习“Java免费学习笔记(深入)”;
- JDK 动态代理要求目标类实现至少一个接口;否则 Spring 会回退到 CGLIB(需添加
spring-boot-starter-aop且类不能是final) - CGLIB 代理会生成子类,因此
final类、final方法无法被增强 - 若想让内部自调用也走 AOP,可用
ApplicationContext.getBean(YourClass.class)获取代理对象再调用,或注入自身(@Autowired当前类)
@Autowired 和 @Resource 到底怎么选?
两者都用于依赖注入,但匹配逻辑不同:@Autowired 默认按类型(byType)匹配,配合 @Qualifier 可指定 Bean 名;@Resource(JSR-250)默认按名称(byName)匹配,name 属性可显式指定 Bean 名。
当存在多个同类型 Bean 时,@Autowired 必须加 @Qualifier,否则启动报错 NoUniqueBeanDefinitionException;而 @Resource 若未指定 name 且找不到同名 Bean,会退回到按类型匹配——这个“兜底行为”容易引发隐性错误。
- 推荐优先用
@Autowired+@Qualifier,语义清晰,IDE 支持好,且与 Spring 生态一致 -
@Resource在需要严格按名称注入(比如对接老代码或某些容器规范)时再考虑 - 字段注入(
@Autowired private XxxService service;)虽简洁,但不利于单元测试和不可变性;构造器注入更安全
Bean 的循环依赖能被 Spring 解决吗?
Spring 仅支持「单例 Bean 之间、Setter/字段注入方式」的循环依赖。它靠三级缓存(singletonObjects、earlySingletonObjects、singletonFactories)提前暴露正在创建中的 Bean 引用,从而打破循环。
但以下情况 Spring 无能为力:
- 原型(
prototype)作用域的 Bean:每次获取都新建,无法缓存中间状态 - 构造器注入的循环依赖:实例化前就要确定依赖,无法提前暴露
- 使用
@Lookup、ObjectFactory、Provider等延迟获取方式时,可能绕过缓存机制 - 涉及 AOP 的循环依赖:如果代理对象尚未生成,而另一方已强依赖该代理,则仍会失败
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'aService': Requested bean is currently in creation
这类错误提示说明 Spring 已放弃尝试解决,需重构依赖关系,比如引入中介 Bean、改用事件驱动或拆分职责。









