这里写目录标题
- 1. @Configuration + @Bean
- 2. @Componet + @ComponentScan
- 3. @Import 注解导入
- 3.1 @Import 直接导入类
- 3.2 @Import + ImportSelector接口
- 3.3 @Import + DeferredImportSelector接口
- 3.4 @Import + ImportBeanDefinitionRegistrar接口
- 4. FactoryBean接口
- 5. BeanDefinitionRegistryPostProcessor接口
1. @Configuration + @Bean
@Configuration 来声明1个配置类,
@Bean 注解声明1个bean,将其加入到Spring容器中。
@Configuration
public class MyConfiguration {@Beanpublic Person person() {Person person = new Person();return person;}
}
2. @Componet + @ComponentScan
@Componet放在类名上面;
@ComponentScan放在配置类上,可以指定一个路径,进行扫描带有@Componet注解的bean,然后加至容器中。
@Component
public class Person {
}@ComponentScan(basePackages = "com.haoqian.beans.*")
public class Demo {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}
3. @Import 注解导入
@Import 注解在进行Spring扩展时经常会用到,它经常搭配自定义注解进行使用,然后往容器中导入一个配置文件。
关于@Import注解,它有四种使用方式。@Import注解的源码如下,可以发现它只能放置在类上。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {/*** 用于导入一个class文件* {@link Configuration @Configuration}, {@link ImportSelector},* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.*/Class<?>[] value();
}
3.1 @Import 直接导入类
public class Person {
}/*** 直接使用@Import导入person类**/
@Import(Person.class)
public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}
3.2 @Import + ImportSelector接口
自定义了一个ImportSelector 接口的实现类,重写selectImports方法,然后将要导入bean的全限定类名写在返回值里面即可。
class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.haoqian.beans.Person"};}
}@Import(MyImportSelector.class)
public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}
3.3 @Import + DeferredImportSelector接口
DeferredImportSelector 它是 ImportSelector 的子接口,所以实现的方法和3.2无异。只是Spring的处理方式不同,它和Spring Boot中的自动导入配置文件 延迟导入有关,非常重要。
class MyDeferredImportSelector implements DeferredImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {// 也是直接将Person的全限定名放进去return new String[]{Person.class.getName()};}
}@Import(MyDeferredImportSelector.class)
public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}
3.4 @Import + ImportBeanDefinitionRegistrar接口
自定义了一个ImportBeanDefinitionRegistrar接口的实现类,重写registerBeanDefinitions方法,然后将要导入bean的beanDefinition 注入到容器中,容器会创建对应的bean。
class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 构建一个beanDefinition.AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();// 将beanDefinition注册到Ioc容器中.registry.registerBeanDefinition("person", beanDefinition);}
}@Import(MyImportBeanDefinitionRegistrar.class)
public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}
@Import 还可以搭配@Configuration注解使用,用于导入一个配置类。
4. FactoryBean接口
FactoryBean接口和BeanFactory千万不要弄混了:
- FactoryBean, 后缀为bean,那么它其实就是一个bean;
- BeanFactory,顾名思义 bean工厂,它是IOC容器的顶级接口;
使用@Configuration + @Bean的方式将 PersonFactoryBean 加入到容器中,注意,没有向容器中注入 Person, 而是直接注入的 PersonFactoryBean 然后可以从容器中拿到Person这个类型的bean。
class PersonFactoryBean implements FactoryBean<Person> {/*** 直接new出来Person进行返回.*/@Overridepublic Person getObject() throws Exception {return new Person();}/*** 指定返回bean的类型.*/@Overridepublic Class<?> getObjectType() {return Person.class;}
}@Configuration
public class Demo1 {@Beanpublic PersonFactoryBean personFactoryBean() {return new PersonFactoryBean();}public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}
5. BeanDefinitionRegistryPostProcessor接口
其实这种方式也是利用到了 BeanDefinitionRegistry,在Spring容器启动的时候会执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法,大概意思就是等beanDefinition加载完毕之后,对beanDefinition进行后置处理,可以在此进行调整IOC容器中的beanDefinition,从而干扰到后面进行初始化bean。
class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();registry.registerBeanDefinition("person", beanDefinition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();MyBeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor = new MyBeanDefinitionRegistryPostProcessor();applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor);applicationContext.refresh();Person bean = applicationContext.getBean(Person.class);}
}