Spring注解详解之组件注册(@Import,FactoryBean)

Spring注解详解之组件注册(@Import,FactoryBean)

@Import

给容器中导入组件的方式大致有三种:

1.包扫描+注解(@Controller,@Service,@Repository,@Component),这适用于自己定义bean

2.通过@Bean注解,这适用于导入第三方包里的bean

3.通过@Import,快速的向容器中注入bean

​ 3.1:@Import(Class):容器中就会自动注册该bean,ID默认全类型

​ 3.2:ImportSelector:返回需要导入的组件的全类名数组

​ 3.3:ImportBeanDefinitionRegistrar:自定义bean定义注册器,手动注册bean

4.使用spring提供的FactoryBean(工厂bean)注入

​ 4.1:通过工厂创建的对象,默认获取的是泛型指定对象,也就是getObject方法获取的对象

​ 4.2:若要获取工厂bean本身对象,需要在bean的ID前加&标识来获取

3.1示例:

//创建一个测试类User
public class User {
}

//配置类
@Configuration
@Import(User.class)
public class MyConfig3 {
}

//测试方法
@Test
public void testImport(){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig3.class);
    String[] names = applicationContext.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}
//输出结果,可见已经注入了user,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
myConfig3
com.ming.bean.User

3.2示例

ImportSelector:返回需要导入的组件的全类名数组

//自定义导入选择器
public class MyImportSelector implements ImportSelector {
    /*
    返回值:需要导入的类的全路径名数组
    AnnotationMetadata:标准@Import注解的类的注解信息
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.ming.bean.Student","com.ming.bean.Person"};
    }
}

//配置类
@Configuration
@Import({User.class, MyImportSelector.class})
public class MyConfig3 {
}

//测试方法
@Test
public void testImport(){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig3.class);
    String[] names = applicationContext.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}
//输出结果
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
myConfig3
com.ming.bean.User
com.ming.bean.Student
com.ming.bean.Person

3.3示例

//自定义bean导入注册器
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /*
    AnnotationMetadata:当前注解@Import类的注解信息
    BeanDefinitionRegistry:Bean的注册类,可以调用registerBeanDefinition手工注册bean,
     */
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean b = registry.containsBeanDefinition("com.ming.bean.Student");
        //判断容器中有student则注入teacher
        if (b) {
            BeanDefinition beanDefinition = new RootBeanDefinition(Teacher.class);
            registry.registerBeanDefinition("teacher",beanDefinition);
        }
    }
}
//配置类
@Configuration
@Import({User.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyConfig3 {
}
//测试方法
@Test
public void testImport(){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig3.class);
    String[] names = applicationContext.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}
//输出结果,存在student并且注入了teacher
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
myConfig3
com.ming.bean.User
com.ming.bean.Student
com.ming.bean.Person
teacher

FactoryBean

使用spring提供的FactoryBean(工厂bean)注入

  • 通过工厂创建的对象,默认获取的是泛型指定对象,也就是getObject方法获取的对象
  • 若要获取工厂bean本身对象,需要在bean的ID前加&标识来获取

示例

//自定义工厂bean
public class UserFactoryBean implements FactoryBean<User> {
    @Override
    public User getObject() throws Exception {
        return new User();
    }
    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
	//默认是true,是单例的,如果重写false,则是多例的
    public boolean isSingleton() {
        return true;
    }
}
//配置类
@Configuration
@Import({User.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyConfig3 {

    //注入自定义的工厂bean
    @Bean
    public UserFactoryBean userFactoryBean(){
        return new UserFactoryBean();
    }
}

//测试方法
@Test
public void testImport(){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig3.class);
    String[] names = applicationContext.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
    Object factoryBean1 = applicationContext.getBean("userFactoryBean");
    Object factoryBean2 = applicationContext.getBean("userFactoryBean");
    System.out.println("userFactoryBean类型:"+factoryBean1.getClass());
    System.out.println(factoryBean1 == factoryBean2);
    Object factoryBean3 = applicationContext.getBean("&userFactoryBean");
    System.out.println(factoryBean3.getClass());

}
//输出结果,发现通过ID:userFactoryBean获取到的对象是getObject方法返回的对象,要获取工厂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
myConfig3
com.ming.bean.User
com.ming.bean.Student
com.ming.bean.Person
userFactoryBean
teacher
userFactoryBean类型:class com.ming.bean.User
true
class com.ming.condition.UserFactoryBean

Spring注解详解之组件注册(@Import,FactoryBean)_第1张图片

在spring的源码,BeanFactroy源码中,有定义这个FACTORY_BEAN_PREFIX前缀,通过上面的描述信息,可以看出通过加该前缀可以获取工厂bean本身

你可能感兴趣的:(spring,java,bean,ioc)