springbean的八种加载方式
总结了一下八种bean的加载方式
bold;">接口
1.XML方式声明bean
不赘述了
2.使用@Component及其衍生注解@Controller 、@Service、@Repository定义bean
@Service
public class BookServiceImpl implements BookService { }
3.ApplicationContex的register方法
public class AppImport { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig5.class); ctx.register(Cat.class); String[] names = ctx.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
4.第三方bean加载方式
@Configuration @ComponentScan("com.itheima") public class SpringConfig { @Bean public DruidDataSource getDataSource(){ DruidDataSource ds = new DruidDataSource(); return ds; } }
初始化实现FactoryBean接口的类,实现对bean加载到容器之前的批处理操作
@Configuration @ComponentScan("com.itheima") public class SpringConfig { @Bean public DruidDataSource getDataSource(){ DruidDataSource ds = new DruidDataSource(); return ds; } } public class SpringConfig8 { @Bean public BookFactoryBean book(){ return new BookFactoryBean(); } }
5.使用@Import注解 解决无侵入式加载,降低耦合问题
@Import(Dog.class)
public class SpringConfig5 { } 被导入的bean无需使用注解声明为bean
public class Dog { }
此形式可以有效的降低源代码与Spring技术的耦合度,在spring技术底层及诸多框架的整合中大量使用
6.ImportSelector接口 在import的基础上解决业务判断问题
导入实现了ImportSelector接口的类,实现对导入源的编程式处理解决根据逻辑业务加载bean的问题
public class MyImportSelector implements ImportSelector { public String[] selectImports(AnnotationMetadata metadata) { boolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Import");//判断SpringConfig5的元数据有哪些特征。有没有import注解 if(flag){ return new String[]{"com.itheima.domain.Dog"}; } return new String[]{"com.itheima.domain.Cat"}; } } @Import(MyImportSelector.class) public class SpringConfig5 { }
7.ImportBeanDefinitionRegistrar接口 //在importselect基础上达到覆盖已有相同名称bean的目的
导入实现了ImportBeanDefinitionRegistrar接口的类,通过BeanDefinition的注册器注册实名bean,实现对
容器中bean的裁定,例如对现有bean的覆盖,进而达成不修改源代码的情况下更换实现的效果。
public class MyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //AnnotationMetadata 同importselect方式判断元数据 BeanDefinition beanDefinition = BeanDefinitionBuilder .rootBeanDefinition(BookServiceImpl2.class) .getBeanDefinition(); registry.registerBeanDefinition("bookService", beanDefinition); } // } @Import(MyRegistrar.class) public class SpringConfig6 { }
8.BeanDefinitionRegistryPostProcessor接口 //在第七种的基础上解决相同名称bean过多,相互覆盖。谁优先级高的问题
导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefinition的注册器注册实名bean,
实现对容器中bean的最终裁定
public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { BeanDefinition beanDefinition = BeanDefinitionBuilder .rootBeanDefinition(BookServiceImpl4.class) .getBeanDefinition(); registry.registerBeanDefinition("bookService", beanDefinition); } } @Import({BookServiceImpl1.class, MyPostProcessor.class, MyRegistrar2.class, MyRegistrar.class}) public class SpringConfig8 { }
如果BookServiceImpl1.class, MyPostProcessor.class, MyRegistrar.class, MyRegistrar.class中bean的名称相同MyPostProcessor.class的优先级最高