单一类型依赖查找
JNDI - javax.naming.Context#lookup(javax.naming.Name)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vrzgmly7-1669257924074)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112306129.png)]](/uploadfile/202402/23cb8622956f.png)
JavaBeans - java.beans.beancontext.BeanContext
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g1ER47wg-1669257924076)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112822387.png)]](/uploadfile/202402/2e340ce2c97ac69.png)
集合类型依赖查找
java.beans.beancontext.BeanContext
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DOUakDJL-1669257924076)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112827221.png)]](/uploadfile/202402/06742a4c61f1a77.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BbGHg86B-1669257924076)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112849605.png)]](/uploadfile/202402/125cf6c4714eeb5.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XlcSZ6MM-1669257924077)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112904560.png)]](/uploadfile/202402/8c378edaa49c119.png)
集合查找方法
层次性依赖查找
java.beans.beancontext.BeanContext
这里要集合 Java Beans Api
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CP5sDgqD-1669257924077)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122113537918.png)]](/uploadfile/202402/45838865df59a77.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vc6gDUz5-1669257924077)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122113631987.png)]](/uploadfile/202402/9fa58a2bb42f1a5.png)
单一类型依赖查找接口- BeanFactory
根据Bean名称查找
getBean(String)
Spring 2.5覆盖默认参数:getBean(String,Object…)
根据 Bean类型查找
Bean实时查找
Spring 3.0 getBean(Class)
Spring 4.1覆盖默认参数:getBean(Class,Object…)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JlGW4QZa-1669257924078)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123110444600.png)]](/uploadfile/202402/d9bf635e4fd84cc.png)
返回一个实例, 这个实例可能是shared(单例)可能是independent(原生), 这里就会告诉你一个不好的特点, 如果是shared的话, 当你的整个一个BeanFactory实例里面, 这个容器里面包含了同样一个实例, 那么之后你每次调用一次就会覆盖它的方法, 这个方式实际上有点不可取的, 那么因此建议采用 BeanFactory 的方式只好是只读方法, 要不你就完全的覆盖相关定义, 比如说你吧以前的BeanDefinition把它进行删除, 后面做一个Override做一个覆盖
Spring 5.1 Bean延迟查找
pom.xml
org.springframework spring-context 5.2.2.RELEASE
getBeanProvider(Class)
package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;/*** * 通过{@link ObjectProvider} 进行依赖查找* * @PACKAGE_NAME: org.xiaoge.thinking.in.spring.dependency.lookup* @Classname ObjectProviderDemo* @Date 2022/11/23 11:23* @Author zhangxiao* @Description TODO*/
public class ObjectProviderDemo { // @Configuration 是非必须注解public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 将当前类 ObjectProviderDemo 作为配置类 (Configuration class)applicationContext.register(ObjectProviderDemo.class);// 启动应用上下文applicationContext.refresh();// 依赖查找集合对象lookupByObjectProvider(applicationContext);// 关闭应用上下文applicationContext.close();}@Beanpublic String helloWord() { // @Bean没有value的时候 方法名称就是 Bean 名称 == "helloWord"return "hello word";}private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {// 通常来说String类型的Bean Spring 上下文是不会定义的, 因此这个时候可以用 注意:只能查唯一Bean多个Bean会报错NoUniqueBeanDefinitionExceptionObjectProvider beanProvider = applicationContext.getBeanProvider(String.class);System.out.println(beanProvider.getObject());}}// 运行结果
hello word
getBeanProvider(ResolvableType)
后面写
根据Bean名称+类型查找: getBean(String,Class)
建议: 不要用覆盖默认参数的形式去查找
集合类型依赖查找接口- ListableBeanFactory
根据Bean类型查找
获取同类型Bean名称列表
getBeanNamesForType(Class)
注意: 这个方法比较BeanDefinition里面的getBeanClassName和FactoryBean里面的getObjectType类型的匹配情况, 所以这个时候还没有涉及到Bean的初始化
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nCOG5tTX-1669257924078)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123133546661.png)]](/uploadfile/202402/7ca30234f537d52.png)
Spring 4.2 getBeanNamesForType(ResolvableType)
获取同类型Bean 实例列表
通过注解类型查找
层次性依赖查找接口– HierarchicalBeanFactory
双亲BeanFactory: getParentBeanFactory()
层次性查找
根据 Bean名称查找
基于containsLocalBean方法实现
package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/**** 层次性 依赖查找 示例** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.dependency.lookup* @Classname HierarchicalDependencyLookupDemo* @Date 2022/11/23 13:52* @Author zhangxiao* @Description TODO*/
public class HierarchicalDependencyLookupDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 讲当前类 HierarchicalDependencyLookupDemo 作为配置类 (Configuration Class)applicationContext.register(HierarchicalDependencyLookupDemo.class);// 1. 获取HierarchicalBeanFactory <- ConfigurableBeanFactory <- ConfigurableListableBeanFactoryConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();System.out.println("当前 BeanFactory 的 Parent BeanFactory : " + beanFactory.getParentBeanFactory());ConfigurableListableBeanFactory parentBeanFactory = createParentBeanFactory();// 2. 设置 Parent BeanFactorybeanFactory.setParentBeanFactory(parentBeanFactory);System.out.println("当前 BeanFactory 的 Parent BeanFactory : " + beanFactory.getParentBeanFactory());// 启动应用上下文applicationContext.refresh();// 当前 Bean 是否在当前容器中displayContainsLocalBean(beanFactory, "user");displayContainsLocalBean(parentBeanFactory, "user");// 当前 Bean 是否在容器中 实现双亲委派displayContainsBean(beanFactory, "user");displayContainsBean(parentBeanFactory, "user");// 关闭应用上下文applicationContext.close();}/*** 查询 Bean 是否 在容器中 实现双亲委派* @param beanFactory* @param beanName*/private static void displayContainsBean(HierarchicalBeanFactory beanFactory, String beanName) {System.out.printf("当前 BeanFactory[%s] 是否包含 Bean[name : %s] : %s\n", beanFactory, beanName, containsBean(beanFactory, beanName));}/*** 递归实现, 查找 Bean 这是 BeanFactoryUtils 没有实现的* @param beanFactory* @param beanName* @return*/private static Boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {if (beanFactory.containsLocalBean(beanName)) {return true;}// 获取父容器BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();// 判断了类型也判断了它是否为空if (parentBeanFactory instanceof HierarchicalBeanFactory) {// 转换类型HierarchicalBeanFactory parentHierarchicalBeanFactory = HierarchicalBeanFactory.class.cast(parentBeanFactory);if (parentHierarchicalBeanFactory.containsLocalBean(beanName)) {return true;}containsBean(parentHierarchicalBeanFactory, beanName);}return false;}/*** 当前 bean 是否在 当前备本地(它自己的容器)容器中* @param beanFactory* @param beanName*/private static void displayContainsLocalBean(HierarchicalBeanFactory beanFactory, String beanName) {System.out.printf("当前 BeanFactory[%s] 是否包含 Local Bean[name : %s] : %s\n", beanFactory, beanName, beanFactory.containsLocalBean(beanName));}/**** @return*/private static ConfigurableListableBeanFactory createParentBeanFactory() {// 创建BeanFactory容器DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);// XML 配置文件 ClassPath 路径String location = "classpath:META-INF/dependency-lookup-context.xml";// 加载配置reader.loadBeanDefinitions(location);return beanFactory;}}// 运行结果
当前 BeanFactory 的 Parent BeanFactory : null
当前 BeanFactory 的 Parent BeanFactory : org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b: defining beans [user,objectFactory,superUser]; root of factory hierarchy
当前 BeanFactory[org.springframework.beans.factory.support.DefaultListableBeanFactory@1e397ed7: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,hierarchicalDependencyLookupDemo]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b] 是否包含 Local Bean[name : user] : false
当前 BeanFactory[org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b: defining beans [user,objectFactory,superUser]; root of factory hierarchy] 是否包含 Local Bean[name : user] : true
当前 BeanFactory[org.springframework.beans.factory.support.DefaultListableBeanFactory@1e397ed7: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,hierarchicalDependencyLookupDemo]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b] 是否包含 Bean[name : user] : true
当前 BeanFactory[org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b: defining beans [user,objectFactory,superUser]; root of factory hierarchy] 是否包含 Bean[name : user] : true 根据 Bean类型查找实例列表
单一类型: BeanFactoryUtils#beanOfType
集合类型:BeanFactoryUtils#beansOfTypeIncludingAncestors
注意: 改方法实现了双亲委派的原则
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uhtppiEk-1669257924079)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123151054825.png)]](/uploadfile/202402/aa0e0be02b7e92e.png)
根据Java 注解查找名称列表
Bean延迟依赖查找接口
org. springframework. beans.factory.ObjectFactory
org. springframework. beans.factory.ObjectProvider
Spring 5 对Java 8 特性扩展
函数式接口
Stream扩展- stream ()
package org.xiaoge.thinking.in.spring.dependency.lookup;import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/**** 通过{@link ObjectProvider} 进行依赖查找** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.dependency.lookup* @Classname ObjectProviderDemo* @Date 2022/11/23 11:23* @Author zhangxiao* @Description TODO*/
public class ObjectProviderDemo { // @Configuration 是非必须注解public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 将当前类 ObjectProviderDemo 作为配置类 (Configuration class)applicationContext.register(ObjectProviderDemo.class);// 启动应用上下文applicationContext.refresh();// 延迟加载依赖查找集合对象lookupByObjectProvider(applicationContext);// 延迟加载lookupIfAvailable(applicationContext);// 延迟加载(查找的是集合)lookupByStreamOps(applicationContext);// 关闭应用上下文applicationContext.close();}private static void lookupByStreamOps(AnnotationConfigApplicationContext applicationContext) {ObjectProvider beanProvider = applicationContext.getBeanProvider(String.class);
// Iterable stringIterable = beanProvider;
// for (String s : stringIterable) {
// System.out.println(s);
// }// Stream -> Method referencebeanProvider.stream().forEach(System.out::println);}/*** 这是个兜底方案, 当没有User Bean 不在容器中时 使用 自己的* @param applicationContext*/private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) {ObjectProvider beanProvider = applicationContext.getBeanProvider(User.class);User user = beanProvider.getIfAvailable(User::createUser);System.out.println("当前 User 对象 : " + user);}@Bean@Primarypublic String helloWord() { // @Bean没有value的时候 方法名称就是 Bean 名称 == "helloWord"return "hello word";}@Beanpublic String message() { // @Bean没有value的时候 方法名称就是 Bean 名称 == "helloWord"return "message";}private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {// 通常来说String类型的Bean Spring 上下文是不会定义的, 因此这个时候可以用 注意:只能查唯一Bean多个Bean会报错NoUniqueBeanDefinitionExceptionObjectProvider beanProvider = applicationContext.getBeanProvider(String.class);System.out.println(beanProvider.getObject());}}// 运行结果
hello word
当前 User 对象 : User{id=1, name='xiaoge'}
hello word
message
依赖查找安全性对比
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qU0KbAWg-1669257924079)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123154119989.png)]](/uploadfile/202402/7513f33f08f4a44.png)
注意:层次性依赖查找的安全性取决于其扩展的单一或集合类型的 BeanFactory 接口
package org.xiaoge.thinking.in.spring.dependency.lookup;import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** 类型安全 依赖查找 示例** @author Zhang Xiao* @since*/
public class TypeSafetyDependencyLookupDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 将当前类 TypeSafetyDependencyLookupDemo 作为配置类 (Configuration class)applicationContext.register(TypeSafetyDependencyLookupDemo.class);// 启动应用上下文applicationContext.refresh();// 演示 BeanFactory#getBean 方法的安全性displayBeanFactoryGetBean(applicationContext);// 演示 ObjectFactory#getObject 方法的安全性displayObjectFactoryGetObject(applicationContext);// 演示 ObjectProvider#ifAvailable 方法的安全性displayObjectProviderIfAvailable(applicationContext) ;// 演示 ListableBeanFactory#getBeansOfType 方法的安全性displayListableBeanFactoryGetBeansOfType(applicationContext);// 演示 ObjectProvider Stream 操作的安全性displayObjectProviderStreamOps(applicationContext);// 关闭应用上下文applicationContext.close();}/*** ObjectProvider* @param applicationContext*/private static void displayObjectProviderStreamOps(AnnotationConfigApplicationContext applicationContext) {ObjectProvider objectProvider = applicationContext.getBeanProvider(User.class);printBeansException("displayObjectProviderStreamOps", () -> objectProvider.forEach(System.out::println));}/*** ListableBeanFactory#getBeansOfType 是否安全* @param beanFactory*/private static void displayListableBeanFactoryGetBeansOfType(ListableBeanFactory beanFactory) {printBeansException("displayListableBeanFactoryGetBeansOfType", () -> beanFactory.getBeansOfType(User.class));}/*** ObjectProvider#getIfAvailable 是否安全* @param applicationContext*/private static void displayObjectProviderIfAvailable(AnnotationConfigApplicationContext applicationContext) {ObjectProvider objectProvider = applicationContext.getBeanProvider(User.class);printBeansException("displayObjectProviderIfAvailable", () -> objectProvider.getIfAvailable());}/*** ObjectFactory#getObject 是否安全* @param applicationContext*/private static void displayObjectFactoryGetObject(AnnotationConfigApplicationContext applicationContext) {// ObjectProvider is ObjectFactoryObjectFactory objectFactory = applicationContext.getBeanProvider(User.class);printBeansException("displayObjectFactoryGetObject", () -> objectFactory.getObject());}/*** BeanFactory#getBean 是否安全* @param applicationContext*/private static void displayBeanFactoryGetBean(AnnotationConfigApplicationContext applicationContext) {printBeansException("displayBeanFactoryGetBean", () -> applicationContext.getBean(User.class));}/*** 打印异常信息* @param source* @param runnable*/private static void printBeansException(String source, Runnable runnable) {System.err.println("===========================================");System.err.println("Source from : " + source);try {runnable.run();} catch (BeansException e) {e.printStackTrace();}}}// 运行结果
===========================================
Source from : displayBeanFactoryGetBean
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.xiaoge.thinking.in.spring.ioc.overview.domain.User' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1126)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.lambda$displayBeanFactoryGetBean$4(TypeSafetyDependencyLookupDemo.java:90)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.printBeansException(TypeSafetyDependencyLookupDemo.java:103)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.displayBeanFactoryGetBean(TypeSafetyDependencyLookupDemo.java:90)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.main(TypeSafetyDependencyLookupDemo.java:30)
===========================================
Source from : displayObjectFactoryGetObject
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.xiaoge.thinking.in.spring.ioc.overview.domain.User' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory$1.getObject(DefaultListableBeanFactory.java:370)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.lambda$displayObjectFactoryGetObject$3(TypeSafetyDependencyLookupDemo.java:82)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.printBeansException(TypeSafetyDependencyLookupDemo.java:103)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.displayObjectFactoryGetObject(TypeSafetyDependencyLookupDemo.java:82)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.main(TypeSafetyDependencyLookupDemo.java:33)
===========================================
Source from : displayObjectProviderIfAvailable
===========================================
Source from : displayListableBeanFactoryGetBeansOfType
===========================================
Source from : displayObjectProviderStreamOps
由此可见建议使用ObjectProvider来进行依赖查找
AbstractApplicationContext 内建可查找的依赖
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9kofvJzg-1669257924080)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123164247234.png)]](/uploadfile/202402/1f1fccb73d17f.png)
注解驱动Spring 应用上下文内建可查找的依赖(部分)

![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tiJRKs5K-1669257924081)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123164505327.png)]](/uploadfile/202402/011cf245e0311df.png)
其实也非常好记, 只需要关注AnnotationConfigUtils就知道了
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jktjKKOn-1669257924081)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123170438893.png)]](/uploadfile/202402/9e2171ddb5cbf17.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PidXZteP-1669257924082)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123170557025.png)]](/uploadfile/202402/4ccbf529df53429.png)
BeansException子类型

NoSuchBeanDefinitionException不做演示, 上面案例有
NoUniqueBeanDefinitionException
package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;/*** {@link NoUniqueBeanDefinitionException} 示例代码** @author Zhang Xiao* @since*/
public class NoUniqueBeanDefinitionExceptionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 将当前类 NoUniqueBeanDefinitionExceptionDemo 作为配置类 (Configuration class)applicationContext.register(NoUniqueBeanDefinitionExceptionDemo.class);// 启动应用上下文applicationContext.refresh();// 由于 Spring 上下文存在两个String类型的 Bean, 通过单一类型查找会报错try {applicationContext.getBean(String.class);} catch (NoUniqueBeanDefinitionException e) {System.err.printf("Spring 应用上下文存在%d个 %s 类型的Bean, 具体原因: %s",e.getNumberOfBeansFound(),String.class.getName(),e.getMessage());}// 关闭应用上下文applicationContext.close();}@Beanpublic String bean1() {return "bean1";}@Beanpublic String bean2() {return "bean2";}
}// 运行结果
Spring 应用上下文存在2个 java.lang.String 类型的Bean, 具体原因: No qualifying bean of type 'java.lang.String' available: expected single matching bean but found 2: bean1,bean2 BeanInstantiationException
package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** {@link BeanInstantiationException} 示例** @author Zhang Xiao* @since*/
public class BeanInstantiationExceptionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 BeanDefinition Bean Class 是一个 CharSequence 接口BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(CharSequence.class);// 注册BeanapplicationContext.registerBeanDefinition("errorBean", beanDefinitionBuilder.getBeanDefinition());// 启动应用上下文applicationContext.refresh();// 关闭应用上下文applicationContext.close();}}// 运行结果
十一月 23, 2022 5:56:42 下午 org.springframework.context.support.AbstractApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorBean': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.lang.CharSequence]: Specified class is an interface
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorBean': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.lang.CharSequence]: Specified class is an interfaceat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1320)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1214)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)at org.xiaoge.thinking.in.spring.dependency.lookup.BeanInstantiationExceptionDemo.main(BeanInstantiationExceptionDemo.java:28)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.lang.CharSequence]: Specified class is an interfaceat org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:70)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1312)... 11 moreProcess finished with exit code 1 BeanCreationException
package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;import javax.annotation.PostConstruct;/*** {@link BeanCreationException} 示例** @author Zhang Xiao* @since*/
public class BeanCreationExceptionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 BeanDefinition Bean Class 是一个 POJO 普通类,不过初始化方法回调时抛出异常BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(POJO.class);// 注册BeanapplicationContext.registerBeanDefinition("errorBean", beanDefinitionBuilder.getBeanDefinition());// 启动应用上下文applicationContext.refresh();// 关闭应用上下文applicationContext.close();}static class POJO implements InitializingBean {@PostConstruct // CommonAnnotationBeanPostProcessor 实现的这个注解, 顺序很重要, 因为PostConstruct注解装饰的方法会先执行public void init() throws Exception {throw new Exception("init() : For purposes...");}@Overridepublic void afterPropertiesSet() throws Exception {throw new Exception("afterPropertiesSet() : For purposes...");}}}// 运行结果
十一月 23, 2022 5:57:12 下午 org.springframework.context.support.AbstractApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorBean': Invocation of init method failed; nested exception is java.lang.Exception: init() : For purposes...
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorBean': Invocation of init method failed; nested exception is java.lang.Exception: init() : For purposes...at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)at org.xiaoge.thinking.in.spring.dependency.lookup.BeanCreationExceptionDemo.main(BeanCreationExceptionDemo.java:28)
Caused by: java.lang.Exception: init() : For purposes...at org.xiaoge.thinking.in.spring.dependency.lookup.BeanCreationExceptionDemo$POJO.init(BeanCreationExceptionDemo.java:38)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)... 12 moreProcess finished with exit code 1 ObjectFactory 与BeanFactory 的区别?
答: 0bjectFactory 与 BeanFactory 均提供依赖查找的能力。
不过 ObjectFactory 仅关注一个 或一种类型的 Bean 依赖查找, 并且自身不具备依赖查找的能力,能力则由 BeanFactory 输出。
BeanFactory则提供了单一类型、集合类型以及层次性等多种依赖查找方式。
根据名称查找

![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8nJA3QGQ-1669257924083)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124100527299.png)]](/uploadfile/202402/0d98e87bf339a75.png)

根据类型查找
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-89L10AE8-1669257924084)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124102640878.png)]](/uploadfile/202402/962e6febff535d0.png)


![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-713k2XRX-1669257924085)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124102926690.png)]](/uploadfile/202402/027cf6d67a501f0.png)
最终还是用了BeanFactory
可以通过改文章, 可以看出它是怎么通过ObjectFactoryCreatingFactoryBean创建ObjectFactory的
BeanFactory. getBean操作是否线程安全?
答: BeanFactory. getBean方法的执行是线程安全的,操作过程中会增加互斥锁。