文章目录
Spring IoC依赖查找:依赖注入还不够吗?依赖查找存在的价值几何?
00、代码实现参考包的路径
01、根据Bean名称进行查找
1.1、实时查找
-
代码演示:
-
public static void main(String[] args) { //1.配置 xml 文件 //2.启动 Spring 应用上下文 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml"); lookUpInRealTime(beanFactory); } private static void lookUpInRealTime(BeanFactory beanFactory) { User user = (User) beanFactory.getBean("user"); System.out.println("实时查找:"+user); }
-
-
理论说明:其实就是简单的从IoC容器当中通过Bean名称获取对应的Bean
1.2、延迟查找
-
代码演示:
-
public static void main(String[] args) { //1.配置 xml 文件 //2.启动 Spring 应用上下文 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml"); lookUpInLazy(beanFactory); } private static void lookUpInLazy(BeanFactory beanFactory){ ObjectFactory<User> objectFactory = (ObjectFactory) beanFactory.getBean("objectFactory"); User object = objectFactory.getObject(); System.out.println("延迟查找:"+object); }
-
-
理论说明:
-
这里会出现一个我们之前没有看到的接口:ObjectFactory,它可以实现延迟查找的功能
-
我们看下它的实现类:ObjectFactoryCreatingFactoryBean,它有一个属性:targetBeanName。我们在xml中配置这个Bean,并且将这个属性赋值,让它指定需要查找的对象。
-
<bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"> <property name="targetBeanName" value="user"/> </bean>
-
所谓的延迟查找,我认为是,我们从IoC容器中可以直接拿到ObjectFactory这个Bean,如果不调用这个Bean的getObject方法的话,我们就不去IoC容器中查找User对象,当我们调用的时候,才会去IoC容器中去查
-
02、根据Bean类型进行查找
2.1、单个Bean对象
-
代码演示:
-
public static void main(String[] args) { //1.配置 xml 文件 //2.启动 Spring 应用上下文 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml"); lookUpByType(beanFactory); } private static void lookUpByType(BeanFactory beanFactory){ User bean = beanFactory.getBean(User.class); System.out.println("实时查找:"+bean); }
-
-
理论说明:
-
首先需要了解beanFactory#getBean(Class requiredType)这个方法是在spring 3.0之后开始支持的,因为spring 3.0才开始支持Java 5版本,Java 5版本开始全面支持泛型
-
这段代码也挺简单的,就是通过 Bean的类型然后去IoC容器中去获取
-
需要注意的是,如果容器中只有一个该类型的Bean的话,程序是正常的,一旦容器中有多个该Bean的类型的时候就会出现问题
-
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.markus.spring.ioc.dependency.domain.User' available: expected single matching bean but found 2: user,super
-
上面就是出现的异常,出现此异常不要担心,也非常好解决。我们打开xml文件,将你想要获取的Bean中配置上 primary=“true” 就可以了。也就是说,在IoC容器中,Bean的地位只有 “主要” 和 “其他”。最终在执行上段代码的时候,控制台就会打印出你配置primary的那个Bean对象。
-
-
2.2、集合Bean对象
-
代码演示:
-
public static void main(String[] args) { //1.配置 xml 文件 //2.启动 Spring 应用上下文 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml"); lookUpCollectionByType(beanFactory); } private static void lookUpCollectionByType(BeanFactory beanFactory){ if (beanFactory instanceof ListableBeanFactory){ ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, User> beansOfType = listableBeanFactory.getBeansOfType(User.class); System.out.println("查找到的所有 User 集合对象:"+beansOfType); } }
-
-
理论说明:
- 这里又出现一个新的接口:ListableBeanFactory,本节只做简单演示,后续章节会对该接口做具体讲解,现在我们可以简单将它理解为:它里面有一个Map集合,这个Map集合存储着每一个类型对应的所有的实体Bean对象,例如:Map<String,User>
- 剩下的就好理解了,通过判断该IoC容器的实例是否是ListableBeanFactory,如果是的话,说明该IoC容器中出现同一类型多个实例的情况。我们可以通过类型获取IoC容器中该类型对应的Map对象,然后打印出来
03、根据Java注解查找
-
代码演示:
-
public static void main(String[] args) { //1.配置 xml 文件 //2.启动 Spring 应用上下文 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml"); lookUpByAnnotation(beanFactory); } private static void lookUpByAnnotation(BeanFactory beanFactory){ if (beanFactory instanceof ListableBeanFactory){ ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, Object> beansWithAnnotation = listableBeanFactory.getBeansWithAnnotation(Super.class); System.out.println(beansWithAnnotation); } }
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-huOSpdBg-1615988755471)(C:\Users\14222\AppData\Roaming\Typora\typora-user-images\image-20210312145254995.png)]
-
-
理论解释:
- 这里有个背景,看过我上面的参考路径你们就会知道,domain包下会有一个SuperUser的实体类,它打上了我们自定义的一个注解:Super,然后我们可以通过listableBeanFactory#getBeansWithAnnotation(Super.class)来获取打这个注解的实例Bean
- 结果就如上图控制台中打印的一样,获取到SuperUser实例对象。