Spring创建Bean的方式可以分为两类,一种是通过BeanDefinition,执行Bean的生命周期方法,完成Bean的创建;另一种是通过FactoryBean的getObject方法,可通过用户自定义的方式创建Bean。
一、通过BeanDefinition
①xml配置
在spring的启动配置文件中配置bean信息,然后通过bean名称获取bean并打印
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext("classpath:springContext.xml");
Object bean = applicationContext.getBean("xmlBeanId");
System.out.println(bean);
}
控制台输出:org.com.lyy.TestBean@6f3b5d16,说明TestBean对象已经存在spring的容器中
②@ComponentScan
@ComponentScan会扫描配置包下包含@Configuration、@Controller、@Service、@Repository、@Component注解的类文件,其中@Configuration、@Controller、@Service、@Repository注解都包含了@Component注解,所以真正被Spring识别解释的是@Component注解
在spring启动配置文件中配置扫描包,然后通过bean类型获取bean并打印
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext("classpath:springContext.xml");
Object bean = applicationContext.getBean(TestBean.class);
System.out.println(bean);
}
控制台输出:org.com.lyy.TestBean@55a147cc,说明TestBean对象已经存在spring的容器中
③@Configuration
当@Configuration的类被Spring扫描到后,因为@Configuration注解引入了@Component注解,所以当前类会被加载到Spring,除此之外,会通过ConfigurationClassParser解释出带有@Bean的方法存储到Set<BeanMethod>中,然后通过ConfigurationClassBeanDefinitionReader遍历Set<BeanMethod>,构建成对应的BeanDefinition,通过BeanDefinitionRegistry向Spring容器注册bean定义信息,这样@Bean的方法就可以实现了向Spring注入Bean
在spring启动配置文件中配置扫描包,然后通过bean类型获取bean并打印
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext("classpath:springContext.xml");
Object bean = applicationContext.getBean(TestBean2.class);
System.out.println(bean);
}
控制台输出:org.com.lyy2.TestBean2@15043a2f,说明TestBean2对象已经存在spring的容器中
④@Import
如果单单通过@Import注解是无法让Spring加载当前类的,通过@Configuration等@Component注解,让当前类能被Spring加载后,通过解释@Import注解的value,加载目标类
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext("classpath:springContext.xml");
Object bean = applicationContext.getBean(TestBean2.class);
System.out.println(bean);
}
控制台输出:org.com.lyy2.TestBean2@738dc9b,说明TestBean2对象已经存在spring的容器中
⑤ImportBeanDefinitionRegistrar
通过@Import注解以及@Component相关注解实现Bean的创建
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext("classpath:springContext.xml");
Object bean = applicationContext.getBean(MyImportBean.class);
System.out.println(bean);
}
控制台输出:org.com.lyy.MyImportBean@298a5e20,说明TestBean2对象已经存在spring的容器中
⑥ImportSelector
通过实现ImportSelector接口,在selectImports方法中把类交给Spring管理,创建Bean
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext("classpath:springContext.xml");
Object bean = applicationContext.getBean(TestBean.class);
System.out.println(bean);
}
控制台输出:org.com.lyy.TestBean@55a147cc,说明TestBean对象已经存在spring的容器中
⑦BeanDefinitionRegistryPostProcessor
通过实现BeanDefinitionRegistryPostProcessor接口,向BeanDefinitionRegistry注册BeanDefinition
二、通过FactoryBean
①通过实现FactoryBean接口,实现getObject()方法生成Bean
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext("classpath:springContext.xml");
Object bean = applicationContext.getBean(TestBean.class);
System.out.println(bean);
}
控制台输出:org.com.lyy.TestBean@3646a422,说明TestBean对象已经存在spring的容器中
以上总结,所以在Spring容器启动的过程中,至少有八种方式让Spring创建Bean。