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 FactoryBean
probable 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 A
un prototipo, cita B
, esta vez B
se va a crear, si B
el prototipo, también citado A
, se A
debe volver a crear, y luego A
cita interior nuevo B
y 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 bean
la definición de marcas de fusión, con el fin de obtener la última detrás de la bean
definición. A continuación, se ocupará de dependsOn
la 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 alreadyCreated
colección de la marca, pero no habrá necesidad de fusionar el conjunto bean
definido, esto dicho antes, porque puede haber demasiados procesador Después de crear bean
la definición, por lo que debería bean
definir 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 lambda
expresiones 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 ObjectFactory
mé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 ObjectFactory
la getObject
creación de bean
objetos, 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-up
método, CGLIB proxies dinámicos para implementar algunas look-up
mé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 null
Sin 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
InstantiationAwareBeanPostProcessor
Tipo de procesador, devuelve un Object
objeto 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 applyBeanPostProcessorsBeforeInstantiation
no 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 existingBean
una 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 TestInstantiationAwareBeanPostProcessor
procesador, a continuación, volver a un TestBean
tema, por lo que otros no pueden llegar a userDao
escribir 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 UserDao
ejemplo:
@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ó TestBean
ejemplo, que no tiene, y por lo tanto no se queja.
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 JDK
proxy dinámico para tratar, de hecho, se puede leer esto para entender AOP
la forma de lograr.
Normal debe ser la siguiente:
el procesador vuelve JDK
después de un proxy dinámico:
TestJDKProxyInstantiationAwareBeanPostProcessor
Esto se puede extender a devolver un JDK
objeto 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 doCreateBean
a 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.