beanFactory.ignoreDependencyInterface(Class> ifc) 方法
相信很多人在看Spring源码的时候的会看到这个方法,但是不知道这个方法是干嘛的,但是从方法名中我们能够大概知道其功能。
先看下Spring源码中这个接口的注释。
大概的翻译前面两句话
1 2 3 | 忽略给定的依赖接口进行自动装配。 通常由应用程序上下文用来注册以其他方式解析的依赖项, 例如通过BeanFactoryAware的BeanFactory或通过ApplicationContextAware的ApplicationContext。 |
一般官方的解释都比较抽象难理解。想要理解这个方法的作用我们得先了解一下Spring中的一个功能。也是让新手容易混淆的一个功能。
自动绑定(自动装配、Autowiring)
我们得先明确一个事实 @Autowired ≠ 自动绑定(Autowiring)其除了单词长的差不多之外没有其他任何联系
因为很多人看到 自动绑定或者Autowiring就以为是 @Autowired
明确这个事实以后我们得介绍一下这个自动绑定的功能有什么作用?
Autowiring byName和byType的区别
开启自动绑定之后会将我们放入到IOC中的对象自动执行其setter方法,在javaBean中一个属性对应着一个setter和一个getter方法
根据约定setXxx其Xxx把首字母改为小写之后就是这个对象中有的属性名。在开启Spring的自动装配之后,一个放入到IOC中的对象中有setTestBean()方法,如果此时自动绑定的规则是 byName 那么Spring会去IOC中寻找testBean这个对象,如果有的会就会执行该setter方法,如果是byType的方式,就是会寻找当前setter方法里对应的参数类型的bean。如果找到多个同样也是抛出异常。
如果开启 Autowiring?
我们从使用Xml的方式到使用@Bean的方式逐一讲解。
如上图所示,我们在使用XML文件方式的时候涉及到了三个类和一个xml文件 AutowiringTest类中只有一个autowiring方法作为我们测试程序的入口。
在XML文件中我们定义了两个Bean标签,将User和Person放入到了IOC中
Person类关联了User并有setUser(User)方法
XML文件源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" default-autowire="byType"> <!-- 这里是关键,将此上下文中的bean都开启了Autowiring模式 可以改成byName--> <bean id="user" class="com.itzijin.dependency.autowiring.domain.User"/> <bean id="person" class="com.itzijin.dependency.autowiring.domain.Person"/> </beans> |
Person类和User类
1 2 3 4 5 6 7 8 9 10 11 | public class Person { private User user; public void setUser(User user) { this.user = user; } } public class User { } |
AutowiringTest 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @ContextConfiguration("classpath:/META-INF/autowiring-demo.xml") @RunWith(SpringRunner.class) public class AutowiringTest { @Autowired private User user; @Autowired private Person person; @Test public void autowiring(){ } } |
此时会自动执行该setter方法。并且我们在setUser中对user属性进行了赋值
上面是基于byType的方式,当然也可以修改成byName的方式。按照我之前说的byName和byType的区别可自行进行验证。
如何通过@Bean的方式开启Autowiring呢?
@Bean中有autowire属性。该属性在Spring5.1的时候已经被标记为过时了
当前程序的类图变成了这样。其中User和Person仍然没有任何变化,但是却新增了一个AutowiredConfiguration类,该类作为配置类,并且XML文件中也发生了变化,Person这个类不在通过XML文件的方式放入到IOC中而是通过配置类的@Bean来放入到IOC中
AutowiringConfiguration类
1 2 3 4 5 6 7 8 | public class AutowiringConfiguration { // 指定autowiring的模式为byType @Bean(autowire = Autowire.BY_TYPE) public Person person() { return new Person(); } } |
我们可以看到,仍然可以进行自定绑定,不然不得不提的是通过@Bean的方式,只对当前类进行自动绑定,在我们上述例子中。我们Person类放入IOC中的时候@Bean上指定了Autowiring模式。那么就只有Person类有Autowiring的能力,如果想要其他类也有则其他类的@Bean上也要为其指定Autowiring模式
beanFactory.ignoreDependencyInterface(Class> ifc) 方法详解
我们了解完Autowiring之后该我们的 beanFactory.ignoreDependencyInterface(Class> ifc) 方法上场了。
Spring在org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory方法中有使用到
我第一次看源码看到这个方法的时候我以为该方法是你在@Autowired的时候不给你进行注入,然而经过我的多方面测试,通过@Autowired仍然能够注入进来,这让我百思不得其解,在网上找了大量资料之后才明白其方法的作用。
这个方法与我们上面讲的Autowiring模式息息相关。
此时我们的类图变成了这样。其中AutowiringConfiguration新增了一个方法,这个方法将BeanFactoryPostProcessorImpl放入到IOC中
AutowiringConfiguration 类
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class AutowiringConfiguration { @Bean(autowire = Autowire.BY_TYPE) public Person person() { return new Person(); } @Bean public BeanFactoryPostProcessor beanFactoryPostProcessor() { return new BeanFactoryPostProcessorImpl(); } } |
BeanFactoryPostProcessorImpl类
1 2 3 4 5 6 7 8 9 10 | public class BeanFactoryPostProcessorImpl implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 我们的 beanFactory.ignoreDependencyInterface()方法善良登场了 beanFactory.ignoreDependencyInterface(Person.class); } } |
我们可以看到在 BeanFactoryPostProcessorImpl中我们的 beanFactory.ignoreDependencyInterface()方法善良登场了。
继续运行程序看看有什么不同
我们发现Person类的setUser(User)方法竟然不执行了?也就是Autowiring模式失效了。
结论
beanFactory.ignoreDependencyInterface() 方法的确是忽略给定接口的自动装配。但是这个自动装配不是 @Autowired