一、依赖注入的几种方式:
1. Set方式注入
1 2 3 4 5 6 7 8
| public class TestServiceImpl implents TestService{ private TestDao testDao; @Autowire public serTestDao(TestDao testDao){ this.testDao = testDao; } }
|
2. 构造函数注入
1 2 3 4 5 6 7 8
| public class TestServiceImpl implents TestService{ private TestDao testDao; @Autowire public TestServiceImpl(TestDao testDao){ this.testDao = testDao; } }
|
3. 注解注入
@Resouece
、@Autowired
、@Inject
注入
1 2 3 4 5 6 7 8
| public class TestServiceImpl implents TestService{ @Autowire private TestDao testDao; }
|
注解 |
描述 |
@Resouece |
通过CommonAnnotationBeanPostProcessor.class实现,属性(name=“**”)指定属性 |
@Autowired |
,当属性required=fales时找不到想对应的Bean不会报错 |
@Inject +@Named |
@Inject 是jsr330中的规范,跟@Autowired 一样通过AutowiredAnnotationBeanPostProcessor.class实现,按类型来查询Bean,@Named 注解用于配置与变量名不一致时 |
@Qualifier |
通常跟@Resource 一起使用,显示指定导入的Bean |
二、循环依赖
1. 循环依赖场景
- A、B两个对象之间互相依赖
- A、B、C之间形成环形依赖(Bean A→Bean B→Bean C→Bean A)
- A对象依赖自身
Bean A 依赖 B,Bean B 同时依赖 A这种情况下出现循环依赖,如下:
Bean A->Bean B->Bean A
但当存在循环依赖时,Spring将无法决定先创建哪个bean,spring将抛出BeanCurrentlyInCreationException异常
2. 解决方法
2.1. 使用注解@lazy
1 2 3 4 5 6 7 8 9
| public class TestServiceImpl implents TestService{ private TestDao testDao; @Autowire public TestServiceImpl(@Lazy TestDao testDao){ this.testDao = testDao; } }
|
2.2. 使用Setter/Field注入
2.3. 实现ApplicationContextAware和InitializingBean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Component public class TestA implents ApplicationContextAware, InitializingBean{ private TestB testB;
private ApplicationContext context; public TestB testB() { return testB; }
@Override public void afterPropertiesSet() throws Exception { testB = context.getBean(TestB.class); }
@Override public void setApplicationContext(final ApplicationContext ctx) throws BeansException { context = ctx; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Component public class TestB { private TestA testA;
private String message = "Hi!";
@Autowired public void setTestA(TestA testA) { this.testA = testA; }
public String getMessage() { return message; } }
|
三、Spring采用三级缓存解决循环依赖
获取Bean源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); private final Set<String> registeredSingletons = new LinkedHashSet<>(256); private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16)); protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } }
|
添加到第1级缓存的源码
1 2 3 4 5 6 7 8 9 10 11 12
| protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
|
添加到第3级缓存的源码
1 2 3 4 5 6 7 8 9 10 11 12 13
| protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
|
创建Bean源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (instanceWrapper == null) { instanceWrapper = this.createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null; Class<?> beanType = instanceWrapper != null ? instanceWrapper.getWrappedClass() : null; boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } this.populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); return exposedObject; }
|
四、三级缓存执行流程
例子:A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象
- A 调用doCreateBean()创建Bean对象:由于还未创建,从第1级缓存
singletonObjects
查不到,此时只是一个半成品(提前暴露的对象),放入第3级缓存singletonFactories
。
- A在属性填充时发现自己需要B对象,但是在三级缓存中均未发现B,于是创建B的半成品,放入第3级缓存
singletonFactories
。
- B在属性填充时发现自己需要A对象,从第1级缓存
singletonObjects
和第2级缓存earlySingletonObjects
中未发现A,但是在第3级缓存singletonFactories
中发现A,将A放入第2级缓存earlySingletonObjects
,同时从第3级缓存singletonFactories
删除。
- 将A注入到对象B中。
- B完成属性填充,执行初始化方法,将自己放入第1级缓存
singletonObjects
中(此时B是一个完整的对象),同时从第3级缓存singletonFactories
和第2级缓存earlySingletonObjects
中删除
。
- A得到“对象B的完整实例”,将B注入到A中。
- A完成属性填充,执行初始化方法,并放入到第1级缓存
singletonObjects
中。
提前暴露的对象,虽然已实例化,但是没有进行属性填充,还没有完成初始化,是一个不完整的对象。 这个对象存放在二级缓存中,对于三级缓存机制十分重要,是解决循环依赖一个非常巧妙的设计。在创建过程中,都是从第三级缓存(对象工厂创建不完整对象),将提前暴露的对象放入到第二级缓存;从第二级缓存拿到后,完成初始化,并放入第一级缓存。