fuente 5.x primavera dieciséis Turísticos explican dos getBean

segmentos doGetBean 2

Continuando con nuestro pasado, la última vez, la presencia de un solo caso, puede ser objetos ordinarios, puede ser FactoryBean, es FactoryBeanprobable que el objeto creado. Esta vez, seguimos a la segunda etapa. Esto se debe principalmente a determinar no se está creando el tipo de prototipo, el tipo de aplicación prototipo no puede resolver el problema de la circulación, se informó anormal. ¿Por qué no el prototipo de referencia circular, ya que se requiere la definición prototipo cada vez que un nuevo objeto, si es Aun prototipo, cita B, esta vez Bse va a crear, si Bel prototipo, también citado A, se Adebe volver a crear, y luego Acita interior nuevo By re-creado, esto sigue así se hace se crea un bucle infinito, por lo que el prototipo de referencia circular no. Si encuentra que la presencia de una planta madre, frijol definición no existe, el tope de la planta madre, permitiendo a la planta para crear uno de los padres, la situación es relativamente pequeña, no lo hacemos profundamente.

		// 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);
				}
			}

segmento doGetBean 3

Continuar el párrafo siguiente, primero determinar si simplemente verificar que el tipo no es el caso se marcará como ya se ha creado, o estaba a punto de crear, y será necesario para establecer beanla definición de marcas de fusión, con el fin de obtener la última detrás de la beandefinición. A continuación, se ocupará de dependsOnla dependencia, no dependerá de la dependencia de prioridad, la charla posterior.

//标记已经创建
			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);
						}
					}
				}

marca markBeanAsCreated

De hecho, en una alreadyCreatedcolección de la marca, pero no habrá necesidad de fusionar el conjunto beandefinido, esto dicho antes, porque puede haber demasiados procesador Después de crear beanla definición, por lo que debería beandefinir hacer una fusión, que es refrescante .

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 párrafo 4 (énfasis aquí)

Por lo general normal a crearlo, si va a juzgar el tipo, se empieza a crear un solo caso en el que un pase de lambdaexpresiones para crear 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)

El Singleton adquisición no el mismo que antes, tenemos que crear un ObjectFactorymétodo, es decir, puede que tenga que llamar a este método de conseguir. Bajo la primera o la primera adquisición si hay un retorno, de lo contrario comenzará a crear un solo caso, hacer primero marcar el principio creó, y luego crear un objeto, y luego borrar la marca, y por último añadido a la colección singleton.

	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, MBD RootBeanDefinition, objeto @Nullable [] args)

Llame a ObjectFactoryla getObjectcreación de beanobjetos, de hecho, que es este método, primero debemos crear un tipo de resolución, el proceso de resolución es más complejo, detrás de la charla, porque sólo tenemos el nombre, no sé para crear qué tipo, y luego se cubre métodos, principalmente el procesamiento de look-upmétodo, CGLIB proxies dinámicos para implementar algunas look-upmétodo, es necesario comprobar no puede cubrir y, a continuación, crear un procesador después del tratamiento, esto es un punto de extensión, luego creó.

@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) {
			...
		}
	}

Ejemplos de resolveBeforeInstantiation pretratamiento

Se procesa antes procesador instanciación. Si no hay procesador devuelve nullSin embargo, haya inicializado directamente, con el tiempo se resuelve ajuste. Si el procesador de procesamiento, tales como los retornos agente dinámico, el objeto se devuelve directamente.

@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;
	}

Ejemplos de los primeros applyBeanPostProcessorsBeforeInstantiation procesador

InstantiationAwareBeanPostProcessorTipo de procesador, devuelve un Objectobjeto que es donde se pueden hacer algunas cosas que el agente, si no hay un procesador de regresar null, regresar directamente.

@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;
	}

Después de applyBeanPostProcessorsAfterInitialization procesador de inicialización

Si encuentra que applyBeanPostProcessorsBeforeInstantiationno se devuelve el objeto null, esto indica que hay un objeto, por lo que será después del proceso de inicialización si se devuelve un valor nulo, entonces no muestra trata directamente de vuelta, y transformar de otro modo. Aquí un poco como un decorador, poner existingBeanuna capa de decoración, y, finalmente, volver, si no decorar un retorno directo.

@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;
	}

Si el procesador no devuelve el objeto, sería se crea el objeto final doCreateBean, hablamos más tarde.

puntos de extensión InstantiationAwareBeanPostProcessor-

Esto puede llevarse a cabo antes de la intervención para crear un objeto, por ejemplo, yo quiero hacer cosas malas, en secreto encontrar un lugar para unirse a un TestInstantiationAwareBeanPostProcessorprocesador, a continuación, volver a un TestBeantema, por lo que otros no pueden llegar a userDaoescribir hasta.

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

clase Configure puede obtener UserDaoejemplo:

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

código de ensayo

  @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);
    }

resultados:

Cuando la inicialización debe ser UserDao, y me dio lo devolvió TestBeanejemplo, que no tiene, y por lo tanto no se queja.
Aquí Insertar imagen Descripción
Entonces conseguimos en los amigos anormales reportados:

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')

Devuelve un proxy dinámico JDK - puntos de extensión

Por supuesto, nadie en el proyecto de hacerlo, lo que hay que hacer, como agente dinámico, vuelvo un JDKproxy dinámico para tratar, de hecho, se puede leer esto para entender AOPla forma de lograr.
Normal debe ser la siguiente:
Aquí Insertar imagen Descripción
el procesador vuelve JDKdespués de un proxy dinámico:
Aquí Insertar imagen Descripción

TestJDKProxyInstantiationAwareBeanPostProcessor

Esto se puede extender a devolver un JDKobjeto proxy dinámico.

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;
    }
}

Para recordar este juez beanName, o puede poner dentro del procesador para el cambio, y no en el tipo de error, tales como:

警告: 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)

Un poco más de tiempo, continuamos volver doCreateBeana explicar.

Pues bien, hoy aquí, esperamos estudio ayuda y entender, no rocíe el Gran Dios ver, comprender solamente su propio aprendizaje, capacidad limitada, por favor excusa.

Publicados 235 artículos originales · ganado elogios 74 · Vistas a 30000 +

Supongo que te gusta

Origin blog.csdn.net/wangwei19871103/article/details/105044402
Recomendado
Clasificación