Spring 5.x source Tour sixteen explain two getBean

doGetBean segments 2

Continuing our last, last time, the presence of a single case, it may be ordinary objects, it may be FactoryBean, it is FactoryBeanlikely to get the object created. This time, we continue to the second stage. This is mainly to determine the type of prototype is not being created, the prototype application type can not solve the problem of circulation, it will be reported abnormal. Why can not the prototype circular reference, because the prototype definition is required every time a new object, if Aa prototype, quote B, this time Bis to be created, if Bthe prototype, also cited A, it Amust be re-created, and then Ainside quote again B, and re-created, this continues it becomes an infinite loop is created, so the prototype circular reference no. If you find the presence of a parent plant, bean definition does not exist, it will go from the parent plant, allowing the plant to create a parent, the situation is relatively small, we do not deeply.

		// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {//原型的循环引用报错
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.如果bean定义不存在,就检查父工厂是否有
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

doGetBean segment 3

Continue following paragraph, first determine whether just check the type is not the case will be marked as already created, or was about to create, and will need to set beanthe definition of merger marks, in order to get the latest behind the beandefinition. Then will deal with dependsOndependency, there will depend on the priority dependency, the back talk.

//标记已经创建
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//获取合并后的bean定义
				checkMergedBeanDefinition(mbd, beanName, args);
				//保证dependsOn的先实例化
				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {//循环依赖,到底谁先创建呢?
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

markBeanAsCreated mark

In fact, into a alreadyCreatedcollection in the mark, but there will need to merge the set beandefined, this said earlier, because there may be too many processor After creating beanthe definition, so there should beandefine do a merger, which is refreshing .

protected void markBeanAsCreated(String beanName) {
		if (!this.alreadyCreated.contains(beanName)) {
			synchronized (this.mergedBeanDefinitions) {
				if (!this.alreadyCreated.contains(beanName)) {//需要重新获取合并一下bean定义,以免元数据被同时修改
					clearMergedBeanDefinition(beanName);
					this.alreadyCreated.add(beanName);
				}
			}
		}
	}

	protected void clearMergedBeanDefinition(String beanName) {
		RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName);
		if (bd != null) {
			bd.stale = true;//需要合并
		}
	}

doGetBean subparagraph 4 (emphasis here)

We generally normal to create it, if you are to judge the type, you begin to create a single case where a pass lambdaexpressions to create bean.

if (mbd.isSingleton()) {//如果是单例,准备创建单例
		sharedInstance = getSingleton(beanName, () -> {
			try {
				return createBean(beanName, mbd, args);
			}
			catch (BeansException ex) {
				destroySingleton(beanName);
				throw ex;
			}
		});
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
	}

getSingleton(String beanName, ObjectFactory<?> singletonFactory)

The acquisition singleton not the same as before, we need to create a ObjectFactorymethod, that is, may need to call this method to get. Under the first or the first acquisition if there is a return, otherwise begin to create a single case, do first mark the beginning created, and then create an object, and then clear the mark, and finally added to the singleton collection.

	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);//获取
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {//单例是否在销毁中,报异常
					throw new BeanCreationNotAllowedException...
				}
				beforeSingletonCreation(beanName);//创建前做个正在创建的标记
				boolean newSingleton = false;//是否创建单例成功,感觉这个用处不大
				...
				try {//调用ObjectFactory的getObject创建bean对象
					singletonObject = singletonFactory.getObject();
					newSingleton = true;//只要获取了就是新单例
				}
				catch (IllegalStateException ex) {
					...
				}
				catch (BeanCreationException ex) {
					...
				}
				finally {
					...
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {//如果是新的单例,就加入到单例集合
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

Call ObjectFactorythe getObjectcreate beanobjects, in fact, which is this method, we must first create a type of resolution, the resolution process is more complex, behind the talk, because we only have the name, do not know to create what type, and then covering methods, mainly processing look-upmethod, CGLIB dynamic proxies to implement some look-upmethod, you need to check can not cover, and then create a processor after treatment, this is an extension point, then created.

@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		...
		RootBeanDefinition mbdToUse = mbd;		
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);//解析出bean的类型
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {//能解析出来,没有BeanClass只有BeanClassName
			mbdToUse = new RootBeanDefinition(mbd);//重新创建RootBeanDefinition
			mbdToUse.setBeanClass(resolvedClass);//设置解析的类型
		}

		try {//准备方法覆盖,处理look-up方法
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			...
		}

		try {//后置处理器在实例化之前处理,如果返回不为null,直接就返回了
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			...
		}

		try {//真正创建
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			...
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			...	
		}
		catch (Throwable ex) {
			...
		}
	}

Examples of pretreatment resolveBeforeInstantiation

It is processed before instantiation processor. If there is no processor returns nullwhether then it directly initialized, eventually setting is resolved. If the processing processor, such as the dynamic agent returns, the object is returned directly.

@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {//非合成的,且有InstantiationAwareBeanPostProcessors
				Class<?> targetType = determineTargetType(beanName, mbd);//获取类型
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);//是否解析了
		}
		return bean;
	}

Examples of the former processor applyBeanPostProcessorsBeforeInstantiation

InstantiationAwareBeanPostProcessorType of processor, it returns an Objectobject that is where you can do some things the agent, if there is not a processor returned null, directly returned.

@Nullable
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

After initialization processor applyBeanPostProcessorsAfterInitialization

If you find that applyBeanPostProcessorsBeforeInstantiationthe object is not returned null, it indicates that there is an object, so it will be after the initialization process if it returns null, then it shows not deal directly back, and otherwise processed. Here a bit like a decorator, put existingBeana layer of decoration, and finally return, if you do not decorate a direct return.

@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

If the processor does not return the object, it would be the final object is created doCreateBean, we speak later.

InstantiationAwareBeanPostProcessor- extension points

This can be carried out before the intervention to create an object, for example, I want to do bad things, I secretly find a place to join a TestInstantiationAwareBeanPostProcessorprocessor, then return to a TestBeansubject, so that others can not get to userDaotype up.

TestInstantiationAwareBeanPostProcessor

public class TestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if(beanName.equals("userDao")){
            TestBean testBean = new TestBean();
            return testBean;
        }

        return null;
    }
}


TestBean

public class TestBean {

}

MyConfig

Configure class can get UserDaoinstance:

@Configuration
public class MyConfig {
    @Bean
    public UserDao userDao(){
        return new UserDaoImple();
    }
}

Test code

  @Test
    public void InstantiationAwareBeanPostProcessorTest() throws Exception {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(MyConfig.class);
        //添加处理器,搞破坏
        applicationContext.getBeanFactory().addBeanPostProcessor(new TestInstantiationAwareBeanPostProcessor());
        applicationContext.refresh();
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        System.out.println(userDao);
    }

result:

When initialization should be UserDao, and I gave him returned TestBeaninstance, he has not, and therefore does not complain.
Here Insert Picture Description
Then we get on the reported abnormal friends:

java.lang.ClassCastException: class com.ww.pojo.TestBean cannot be cast to class com.ww.pojo.UserDao (com.ww.pojo.TestBean and com.ww.pojo.UserDao are in unnamed module of loader 'app')

Returns a JDK dynamic proxy - extension points

Of course, no one in the project so doing, the right thing to do, such as dynamic agent, I come back a JDKdynamic proxy to try, in fact, you can read this to understand AOPhow to achieve.
Normal should be this:
Here Insert Picture Description
the processor returns JDKafter a dynamic proxy:
Here Insert Picture Description

TestJDKProxyInstantiationAwareBeanPostProcessor

This is can be extended to return a JDKdynamic proxy object.

public class TestJDKProxyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if(beanName.equals("userDao")){
            UserDao userDaoimpl=new UserDaoImple();
            UserDao userDao= (UserDao) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{UserDao.class}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("我是JDK动态代理的");
                    method.invoke(userDaoimpl);
                    return null;
                }
            });
            return userDao;
        }

        return null;
    }
}

To remember this judge beanName, or you might put inside the processor to change, and not on the error type, such as:

警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' is expected to be of type 'org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor' but was actually of type 'com.ww.pojo.TestBean'



org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' is expected to be of type 'org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor' but was actually of type 'com.ww.pojo.TestBean'

	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:395)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:89)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:706)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532)
	at com.ww.AppTest.InstantiationAwareBeanPostProcessorTest(AppTest.java:38)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

A little longer, we continue back doCreateBeanto explain.

Well, here today, we hope to help study and understand, do not spray the Great God see, understand only their own learning, limited capacity, please excuse.

Published 235 original articles · won praise 74 · views 30000 +

Guess you like

Origin blog.csdn.net/wangwei19871103/article/details/105044402