循环依赖是指两个或多个模块、类、组件之间相互依赖,形成一个依赖闭环。导致的无法确定加载或初始化。
例如:
@Service
public class A {
@Autowired
private B b;
}
@Service
public class B {
@Autowired
private A a;
}
//或者自己依赖自己
@Service
public class A {
@Autowired
private A a;
}
第一种方法:Spring中 使用三级缓存来解决循环依赖问题
具体方法见后面这个博客:Spring中的循环依赖问题和三级缓存
第二种方法:使用@lazy注解
为什么可以解决?
代理对象
进行“填充”,然后继续完成Bean A的创建。Core Container (核心容器)
AOP(面向切面编程)
Data Access(数据访问)
Web 层
Spring的扩展模块
… …
IOC:(Inversion of Control):是通过依赖注入(DI)实现的,IOC让对象的创建和管理由容器负责,而不是由对象自身控制。
IoC即:控制反转,是一种思想而不是一种技术。
本质上控制的是对象的创建,IOC容器根据配置文件来创建对象,在对象的生命周期内,在不同时期根据不用的配置进行对象的创建和改造。
什么被反转了?
DI(Dependency Injection,依赖注入)普遍认为是Spring框架中用于实现 控制反转(IOC)的一种机制,DI的核心思想是由容器负责对象的依赖注入,而不是对象自行创建或查找依赖对象。
通过DI,Spring容器在创建一个对象时,会自动将这个对象依赖注入进去,可以让对象与其依赖的对象解耦,提升系统的灵活性和可维护性。
任何通过Spring容器实例化、组装和管理的Java对象都被称为Spring Bean。Bean可以在Spring容器中被定义并且通过依赖注入来与其他Bean进行相互依赖。
即:Bean 可以看作是Spring 容器中的一个对象,它的生命周期(创建、初始化、使用、销毁等过程)完全由Spring 容器控制。
Spring Bean 的生命周期
标签来指定类、构造器参数和依赖关系BeanFactory 是IOC的底层容器:负责管理和配置应用中的 Bean,他是 Spring IOC 容器的基础实现,提供了创建和管理 Bean 的基本功能
BeanFactory的实现:
我们调用 getBean,这个就是 BeanFactory定义的方法,通过他得到 Bean。
不过 BeanFactory 本身是一个接口,一般我们所说的 BeanFactory 是指他的实现类:
FactoryBean 是 Spring 提供的一个特殊接口,允许开发者通过自定义的逻辑创建复杂的 Bean 示例,与普通的 Bean 不同,通过FactoryBean 创建的 Bean 不一定是 FanctoyBean 本身,而可能是他生产的对象。
提供了一种灵活的方式来控制 Bean 的创建过程,尤其适用于生成动态代理或需要复杂配置的Bean
FactoryBean
接口的Bean,通过它可以自定义复杂对象的创建逻辑,Spring 容器会调用 getObject()
方法来获取实际的Bean实例实例:
1、实现 FactoryBean 接口:定义一个类实现FactoryBean
接口,并实现三个方法:
public class MyFactoryBean implements FactoryBean<MyBean> {
@Override
public MyBean getObject() throws Exception {
// 复杂逻辑创建 MyBean 对象
return new MyBean();
}
@Override
public Class<?> getObjectType() {
return MyBean.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
2、使用 FactoryBean:在Spring 容器中定义 FactoryBean,Spring 会通过 FactoryBean 创建实际的 Bean 实例:
<bean id="myBean" class="com.example.MyFactoryBean"/>
这样我们使用 getBean("myBean")
会得到MyFactoryBean#getObject 的结果
Object Factory 是 Spring 框架中的一个接口,主要用于:延迟获取 Bean 实例
ObjectFactory 提供了一种延迟加载的机制,通过 getObject()方法返回一个 Bean 的实例。使用 ObjectFactory 可以避免在容器启动时立即创建所有 Bean,在真正需要使用 Bean 时才会从 Spring 容器中获取该 Bean 的实例。
ObjectFactory使用场景
ApplicationContext 是Spring 框架的一个核心接口,是Spring IoC容器的高级形态,提供了BeanFactory 更丰富的功能。它是Spring 一应用程序的核心,不仅负责创建和管理Bean,还提供对Bean的全面管理以及对应用程序环境的支持,它是多个底层接口组合后的接口,它主要提供五大功能:
核心容器
BeanFactory 是 Spring 的核心容器,是ApplicationContext 的父接口。SpringBoot默认返回ConfigurableApplicationContext 是 ApplicationContext 的子接口,它组合了一个 ConfigurableListableBeanFactory,并提供它对外提供的 BeanFactory 的功能,
一共六种作用域:
构造器注入,Spring 提倡构造函数注入,因为构造器注入返回给客户端使用的时候一定是完整的
public class MyService {
private final MyDependency myDependency;
@Autowired
public MyService(MyDependency myDependency) {
this.myDependency = myDependency;
}
}
setter 注入:可选的注入方式,在有变更的情况下,可以重新注入
public class MyService {
private MyDependency myDependency;
@Autowired
public void setMyDependency(MyDependency myDependency) {
this.myDependency = myDependency;
}
}
字段注入:就是@Autowired 标记字段
方法注入:就是@Autowired 标记方法
接口回调注入:就是实现 Spring 定义的一些内建接口,例如: BeanFactoryAware,会进行 BeanFactory 的注入。
AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,用于将跨领域的关注点(如日志记录、安全检查、事务管理等)与业务逻辑分离开,它允许开发者通过“切面”(Aspect)将这些通用功能模块化,并将其应用到应用程序中的多个地方,从而避免代码重复。
切面:是一个模块,包含跨领域的关注点,比如日志、事务等,它可以包含多个通知(Advice)来定义在何时何地应用特定的逻辑
@Aspect
public class LoggingAspect{
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(){
System.out.println("Logging before method execution");
}
}
连接点:是程序执行中的一个特定位置,例如方法调用或异常抛出。AOP允许在这些点上插入切面逻辑。
通知:通知是定义在连接点执行的操作,常见的通知类型包括:
切入点:定义了在何处应用通知,通常是通过表达式来匹配方法或类,例如可以定义某个包下的所有方法未切入点。
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods(){}
织入(Weaving):织入是将切面应用到目标对象的过程。可以在编译时、类加载时或运行时进行织入
通俗理解:通过代理的方式,在调用想要的对象方法的时候,进行拦截处理,执行切入的逻辑,然后再调用真正的方法实现。