1、Maven 中的dependencyManagement和dependency的区别
首先maven可以通过子模块依赖父模块的方式获得父模块的所有依赖,极大便利的提供了对项目以来的管理,但是在使用这种方式实现对依赖的管理时,子模块不可避免的会引入父模块中存在,但是对自身来说并不需要的依赖,导致引入了冗余的jar包,但使用dependencyManagement 则可以有效避免这个问题。dependencyManagement 具有一下两个特性:
1、在该元素下声明的依赖不会引入到模块中,只有在dependeny中同样声明了该依赖,才会引入到模块中
2、该元素能够约束dependency 下依赖的使用,如果在dependency 中未指定版本,则会使用dependencyManagement 的版本,否则就会覆盖dependencyManagement 指定的版本。
2、@Import使用
@Import
注解提供了类似 @Bean
注解的功能,向Spring容器中注入bean
从定义上来看,@Import
注解非常简单,只有一个属性value()
,类型为类对象数组,如value={A.class, B.class}
,这样就可以把类A和B交给Spring容器管理。但是这个类对象需要细分为三种对象,也对应着@Import
的三种用法如下:
- 普通类
- 实现了ImportSelector接口的类(这是重点~Spring Boot的自动配置原理就用到这种方式)
- 实现了ImportBeanDefinitionRegistrar接口的类
普通类
-
@Configuration @Import({Student.class}) public class MyConfig { @Bean public Person person01() { Person person = Person.builder().id(1l).name("shepherd").age(25).build(); return person; } public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); // 遍历Spring容器中的beanName for (String beanDefinitionName : beanDefinitionNames) { System.out.println(beanDefinitionName); } } }
myConfig com.shepherd.common.config.Student person01
这里默认注入了一些Spring内部bean和我们在MyConfig
中注入的bean,@Import({Student.class})
把Student
类注入到了Spring容器中,beanName默认为全限定类名com.shepherd.common.config.Student
,而@Bean
注入的默认为方法名,这也是两者的区别。
实现了ImportSelector接口的类
是@Import
最常用的方式,Spring Boot的自动装配原理就用到了这种方式
ImportSelector接口
selectImports( )
返回一个包含了类全限定名的数组,这些类会注入到Spring容器当中。注意如果为null,要返回空数组,不然后续处理会报错空指针getExclusionFilter()
该方法制定了一个对类全限定名的排除规则来过滤一些候选的导入类,默认不排除过滤。该接口可以不实现
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.shepherd.common.config.Student",
"com.shepherd.common.config.Person"};
}
}
@Configuration
@Import({MyImportSelector.class})
public class MyConfig {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
// 遍历Spring容器中的beanName
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
Spring没有把MyImportSelector
当初一个普通类进行处理,而是根据selectImports( )
返回的全限定类名数组批量注入到Spring容器中。当然你也可以实现重写getExclusionFilter()
方法排除某些类,比如你不想注入Person类,你就可以通过这种方式操作一下即可
实现ImportBeanDefinitionRegistrar接口的类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
//使用 BeanNameGenerator自动生成beanName
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Person.class);
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
String beanName = importBeanNameGenerator.generateBeanName(beanDefinition, registry);
registry.registerBeanDefinition(beanName, beanDefinition);
}
// 手动指定beanName
// @Override
// public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Student.class);
// AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
// registry.registerBeanDefinition("student001", beanDefinition);
// }
}
里只能注入一个bean,所以只能实现一个方法进行注入,如果两个都是实现,前面的一个方法生效。