首先,Spring往IOC容器中注册Bean的方法有以下几种:
1、通过包扫描+注解的方式;如@Controller,@Service,@Reposity,@Component;
2、通过@Bean的形式;
3、通过@Import的形式;
4、通过BeanFactory的形式进行注册;
前2点在上面的有所记录过,今天就主要记录一下在学习如何使用@Import和BeanFactory进行组件注册;首先看一下@Import;
一、@Import
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
* or regular component classes to import.
*/
Class<?>[] value();
}
首先可以看到@Improt需要传入一个泛型数组,也就是说@Import({XXX.class,BBBB.class});其次,还有2个注意的地方,一个叫做ImportSelector(选择器)和ImportBeanDefinitionRegistrar(Bean定义注册器)。ImportSelector和ImportBeanDefinitionRegistrar都是两个接口;换句话说就是@Import可以使用自定义组件注入,也可以使用实现ImportSelector或者是ImportBeanDefinitionRegistrar的方式进行注入;
(1)、@Import({XXX.class,BBBB.class})的方式
定义一个Animal类,Dog类,Pig类。然后通过@Import({XXX.class,BBBB.class})的方式,进行注入,上代码;
MyConfig.class
@Configuration
@Import({Dog.class,Person.class})
public class Myconfig {
}
--------------------------------------
测试类代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringTrainApplicationTests {
@Test
public void contextLoads() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Myconfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
结果如下:
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
myconfig
com.snail.tool.bean.Dog
com.snail.tool.bean.Person
可以看到,Dog和Person都有进入到IOC容器中,这里有一点需要注意到,就是通过@Import注入的Bean,它的id默认是全类名;
(2)、ImportSelector选择器情况
首先ImportSelector是一个接口,需要进行实现改接口,新建一个AnimalImportSelector 类,实现ImportSelector接口,如下代码:
public class AnimalImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.snail.tool.bean.Pig","com.snail.tool.bean.Cat"};
}
}
注意:
1、AnnotationMetadata 就是标注了@Import的当前类,可以通过该参数,拿出当前类的一些属性;
2、selectImports方法,返回的是一个数组;
3、@Import方式注入的Bean,id默认是全类名;如果不是全类名,会报错上下文无法找到;
运行结果:
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
myconfig
com.snail.tool.bean.Dog
com.snail.tool.bean.Person
com.snail.tool.bean.Pig
com.snail.tool.bean.Cat
可以看到,com.snail.tool.bean.Pig和com.snail.tool.bean.Cat已经在IOC容器中了
(3)、ImportBeanDefinitionRegistrar;同样的,这也是一个借口,先一个PersonImportBeanDefinitionRegistrar类来实现它,代码如下:
public class PersonImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
注意:
1、AnnotationMetadata:还是被@Import注解的当前类,可以通过该参数,拿到当前类的一些属性;
2、BeanDefinitionRegistry:Bean定义注册器,是一个接口,接口中过的方法如下:
void registerBeanDefinition(String var1, BeanDefinition var2) ;
void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String var1);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String var1);
主要用到的是registerBeanDefinition这个方法,这个方法中,有一个BeanDefinition,用于定义作用域等属性,var1是Bean的id可以自定义;
MyConfig.class
@Configuration
@Import({Dog.class,Person.class,AnimalImportSelector.class,PersonImportBeanDefinitionRegistrar.class})
public class Myconfig {
}
---------------------------------
测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringTrainApplicationTests {
@Test
public void contextLoads() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Myconfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
运行结果:
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
myconfig
com.snail.tool.bean.Dog
com.snail.tool.bean.Person
com.snail.tool.bean.Pig
com.snail.tool.bean.Cat
Student
可以看到,Student是被注册进来的;
springboot源码中,大量使用的都是@ImportSelector进行组件注入;通过ImportBeanDefinitionRegistrar,可以让开发者自定义组件信息;
二、BeanFactory,Bean工厂类;通过实现FactoryBean<T>的方法,进行Bean的设定,其中T代表泛型;这里创建一个类型为Teacher的PersonBeanFactory类;
public class PersonBeanFactory implements FactoryBean<Teacher> {
//返回bean对象
@Override
public Teacher getObject() throws Exception {
return new Teacher();
}
//返回bean的类型
@Override
public Class<?> getObjectType() {
return Teacher.class;
}
//设置作用于范围
@Override
public boolean isSingleton() {
return false;
}
}
然后在配置类中进行配置,测试类中进行测试,代码如下:
Myconfig.class
@Configuration
public class Myconfig {
@Bean
public PersonBeanFactory personBeanFactory(){
return new PersonBeanFactory();
}
}
-------------------------------------
测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringTrainApplicationTests {
@Test
public void contextLoads() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Myconfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
运行结果:
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
myconfig
personBeanFactory
可以看到有一个叫做personBeanFactory的Bean。
我们的BeanFactory是泛型指定,那看看personBeanFactory这个Bean的类型是什么?测试类代码:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringTrainApplicationTests {
@Test
public void contextLoads() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Myconfig.class);
Object personBeanFactory = applicationContext.getBean("personBeanFactory");
System.out.println(personBeanFactory.getClass() );
}
}
运行结果:
class com.snail.tool.bean.Teacher
以上便是4中方式,往IOC容器中注册Bean的方法刚开始学习,慢慢做积累;