背景:
实例化对象后,需要设置字段,即依赖注入,两种:set方法注入和构造方法注入。
流程:
先寻找整个类的注入点,就是打了@autowired的字段或方法,然后根据类型、名称去找
常用依赖注入注解辨析:
@Inject
:来自JSR 330规范。按类型注入。@Resource
:是Java EE的一部分。先按名字注入,再按类型注入。@Autowired
:来自spring。按类型注入,再按名字注入。
@Qualifier
:来自spring
。与@autowored一起用,指定如果类型相同,需要注入的类名。背景:
a类有b,b类有a。
a实例化,注入b,发现beanMap中没有b,开始生成b,b实例化,注入a,发现beanMap中没有a,所以生成a,生成a需要b,生成b又需要a,所以就无限循环了。
解决措施:
a实例化后,就放入map中,这样b就能获取到a了,b就能生成了,就能注入a,a就能接着生成了。但这有个问题,a如果有aop,则a是代理对象,但b中的a是被代理对象。所以就要三级缓存。
流程:
1、a实例化后,放入三级缓存map(singletonFactories),注入b,发现没有b
2、需要生成b,实例化b,注入a,从singletonFactories中获取,会执行a中lambda的方法得到a或a的代理对象(如果a有aop,则该方法会返回a代理对象,否则就返回它自己,并把代理对象或者a放入二级缓存map(earlySingletonObjects)中,如果有aop还会放入earlyProxyReferences中记录下),b注入a或a的代理对象,b初始化,b创建好
3、a注入b,a继续生命周期,a初始化,a进行或不进行aop(如果earlyProxyReferences中有a,则说明已经进行了aop就无需进行,否则需要进行aop),把a放入一级缓存(singletonObjects)
三级缓存:
一级singletonObjects:放完整生命周期的bean
二级earlySingletonObjects:放未经过完整生命周期的bean。
三级singletonFactories:放lambda表达式。
加了3级缓存流程是这样:
a需要注入b,从一级缓存中找b,有就直接获取,没有发现则从二级缓存中找b,找到就返回给a,没有发现,则从三级缓存中调用lambda获取,找到就返回给a,没找到就创建b。
JCP(Java Community Process,Java社区进程)是Java社区的一个重要组织,负责Java技术的标准化工作。JSR(Java Specification Request)是jcp的一个提案。
JSR 330(Java Specification Request 330)是Java社区提出的一个规范,全称为“Dependency Injection for Java”,即Java的依赖注入规范。这个规范主要是为了提供一种标准化的方式来进行依赖注入,以提高代码的可重用性、可测试性和可维护性。
JSR 330,定义了一系列用于依赖注入的注解,如@Inject
、@Scope
、@Named
等。
@Inject
:按类型注入。用于标记需要依赖注入的字段、构造方法或方法。@Scope
:用于指定bean的作用域,如单例(Singleton)、原型(Prototype)等。不过,需要注意的是,JSR 330的@Scope
注解主要用于定义自定义作用域,而具体的作用域实现则依赖于DI框架。@Named
:用于为bean提供一个名称,以便在按名称进行注入时使用。类似于Spring的@Qualifier
与Spring的集成
@Inject
等JSR 330注解来进行依赖注入。不过,需要注意的是,虽然Spring支持JSR 330注解,但它也提供了自己的一套注解(如@Autowired
、@Component
、@Scope
等),这些注解在功能上可能与JSR 330注解有所重叠,但在某些方面可能提供了更多的灵活性和功能。