소개
에서 이전 기사 , 우리는 분석에 집중 흐름 의 getObjectType의 메소드 의 FactoryBean을 , 그리고 마지막으로, 우리는 (IOrderService.calss)에 전달 클래스 타입하고 정의의 FactoryBean 서브 클래스 간의 관계를 설명하는 일반적인 흐름도를 그린 연결 방법, 즉 getBean (IOrderService.class)를 호출 하면 맨 아래 계층은 결국 factoryBean.getObjectType ()을 호출 합니다.
이 기사에서는 FactoryBean 이 어떻게 Spring 컨테이너가 getObject () 를 호출하여 생성 된 Bean 을 관리 하도록 허용하는지 분석 한 다음 이전 기사의 후속 분석 (아래 참조)을 분석합니다.
DefaultListableBeanFactory # resolveNamedBean
이때 일부 변수 값은 다음과 같습니다.
- requiredType : IOrderService.class
- 후보 이름 : {“orderFactoryBean”}
후보 이름 배열의 길이가 1이기 때문에 getBean (beanName, requiredType, args) 메소드에 들어가고 ,이 메소드는 doGetBean 메소드를 호출하고 , doGetBean은 Spring 컨테이너 초기화의 매우 중요한 부분이지만 여기에서는 너무 많은 Spring Bean 수명을 분석하지 않습니다. 주기의 내용은이 기사에서 FactoryBean과 관련된 내용에만 집중합니다.
AbstractBeanFactory # doGetBean (일부 관련없는 코드 생략)
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//转换传入的BeanName的值,如&name变为name 以及别名(alias)的转换
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//调用getSingleton方法 从Spring容器中获取单例Bean,下面再具体分析此方法
//这里的beanName为orderFactoryBean,获取到的是它对应的OrderFactoryBean实例(因为我们有添加@Component注解,spring容器中已创建该bean)
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//这里是根据获取到的OrderFactoryBean实例本身去获取对象
//注意这里传入了name和转换后的beanName
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
DefaultSingletonBeanRegistry # getSingleton , Spring 컨테이너에서 싱글 톤 빈을 가져옵니다.
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//先从singletonObjects单例池(一级缓存)中获取Bean,singletonObjects是一个ConcurrentHashMap
//key是beanName value是单例Bean
Object singletonObject = this.singletonObjects.get(beanName);
//如果单例池中不存在,并且是当前正在创建中的Bean
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 加锁
synchronized (this.singletonObjects) {
//从二级缓存中获取早期的bean
singletonObject = this.earlySingletonObjects.get(beanName);
//如果没有获取到,并且允许提前引用相应的Bean(依赖注入)
if (singletonObject == null && allowEarlyReference) {
//singletonFactories俗称三级缓存,key:beanName,value:ObjectFactory
// 这个ObjectFactory是一个函数式接口,所以支持Lambda表达式:() -> getEarlyBeanReference(beanName, mbd, bean)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//从ObjectFactory中获取Bean实例
singletonObject = singletonFactory.getObject();
//放入earlySingletonObjects这个Map二级缓存中,依赖注入时用到
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
이 방법은 매우 중요하며 Spring 컨테이너의 3 단계 캐시를 포함합니다.
- 레벨 1 캐시 : singletonObjects , 완전한 라이프 사이클을 거친 빈 객체 를 캐시합니다.
- Second-level cache : earlySingletonObjects , singletonObjects보다 더 이른 것은 캐시 된 bean 객체가 초기 bean 객체임을 나타냅니다 (또는 : 캐시 이후에 얻은 프록시 객체 는 AOP 를 위해 미리 원래 객체 를 취함 ). 은 무슨 뜻인가요? Bean이 earlySingletonObjects에 들어가기 전에 Bean의 라이프 사이클이 완료되지 않았 음을 나타냅니다.
- 3 단계 캐시 : singletonFactories , 캐시는 객체를 생성하는 데 사용되는 객체 팩토리를 나타내는 ObjectFactory입니다.
2 단계 캐시는 주로 Spring에서 순환 종속성을 해결하는 데 사용됩니다. SingletonFactories는 주로 AOP 이후 얻은 원본 객체와 프록시 객체를 생성하는 데 사용됩니다. 자세한 내용은 "[인터뷰 질문] 마지막으로 누군가가 Spring의 순환 종속성을 명확하게 설명 할 수 있습니다. " , 잘 작성되었습니다.
아래 주제로 돌아가서 AbstractBeanFactory # getObjectForBeanInstance 를 분석해 보겠습니다.
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果传进来的OrderFactoryBean不属于FactoryBean的实例,则直接返回当前实例(表示它是普通的bean)
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 如果是FactoryBean子类bean
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {// 缓存中获取
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
//如果能走到这里来,说明这个bean实例是FactoryBean类型的
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 从该方法名字看出:从FactoryBean中获取对象,下面再具体分析
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
分析FactoryBeanRegistrySupport # getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//FactoryBean类型的实例是否单例
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
//从缓存中获取
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//缓存获取不到,则调用doGetObjectFromFactoryBean方法从FactoryBean中获取bean对象
//这里是调用的FactoryBean的getObject方法来获取的,具体看这一步
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
//再从缓存中获取一次
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
//如果上一步的缓存中获取到了,则用缓存中的替代FactoryBean中获取的bean
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
//调用BeanPostProcessor中的postProcessAfterInitialization方法进行处理
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
//添加到factoryBeanObjectCache中缓存,key为beanName
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
//FactoryBean的实例非单例情况
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
doGetObjectFromFactoryBean 분석 , 여기 객체를 얻기 위해 호출 된 FactoryBean의 getObject 메소드 가 있습니다.
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 终于看到了FactoryBean中的getObject(),真相大白
object = factory.getObject();
}
}
return object;
}
대략적인 순서도 ( 인용 )
요약하자면
대략적인 과정 : 우리가 전달한 클래스 유형에 따라 Spring 컨테이너의 모든 BeanName을 루프 한 다음 beanName에 따라 해당 Bean 인스턴스를 획득하고 획득 한 Bean 인스턴스가 FactoryBean 유형의 Bean인지 확인합니다. 그렇다면 FactoyBean의 getObjectType 메소드를 호출합니다. 클래스를 획득하고 획득 한 클래스를 전달 된 클래스와 일치시키고 일치하는 경우이 beanName과 전달 된 클래스 간의 매핑 관계를 설정합니다. 그런 다음 beanName에 따라 Spring 컨테이너에서 해당 FactoryBean 인스턴스 빈을 얻고 FactoryBean의 getObject 메서드를 호출하여 메서드에서 사용자 정의 빈을 얻습니다.
참조 : https://conan.blog.csdn.net/article/details/79588391
● 알리바바는 왜 90 초 안에 100 억을 저항 할 수 있습니까? -서버 측 동시성이 높은 분산 아키텍처의 진화
● B2B 전자 상거래 플랫폼 --ChinaPay UnionPay 전자 결제 기능
● Zookeeper 분산 잠금을 배우고 면접관이 감탄하면서 당신을 볼 수 있도록하십시오
● SpringCloud 전자 상거래 스파이크 마이크로 서비스 -Redisson 분산 잠금 솔루션
더 많은 좋은 기사를 확인하고 공식 계정을 입력하십시오.
깊고 충만한 공개 계정 0.0