Sping 源码理解(一)注解驱动
1 组件添加
/** * 给容器中注册组件 * 1》包扫描+组件标注注解(@Controller @Service @Repository @Component [自己写的类]) * 2》@Bean [导入的第三方包里面的组件] * 3》@Import [快速给容器中导入一个组件] * 1)@Import(要导入到容器中的组件):容器中就会自动注册这个组件,id默认是全类名 * 2)ImportSelector:返回需要导入的组件的全类名数组; * 3)ImportBeanDefinitionRegistrar: 手动注册bean到容器中 * 4》使用Spring提供的FactoryBean(工厂bean) * 1)默认获取奥的是工厂bean调用getObject创建的对象 * 2)要获取工厂bean本身,我们需要给id前面加一个& * &colorFactoryBean * */
除了 @Controller @Service @Repository @Component基本方式以外;还可以通过 @Configuration @Bean @ComponentScan(自动扫描组件TypeFilter过滤) @ Import 的方式添加组件
Test.java
@Test public void test01() { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String name : beanDefinitionNames) { System.out.println(name); } Object person = applicationContext.getBean("person"); Object person1 = applicationContext.getBean("person"); System.out.println(person == person1); }
MainConfig.class
//配置类==配置文件 @Configuration @ComponentScan(value = "com", includeFilters = { // @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}), 注解类型 // @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}), //制定类型过滤 @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}) //自定义 }, useDefaultFilters = false)//默认过滤开关 //excludeFilters = filter[] //includeFilters= filter[] useDefaultFilters = false关闭默认过滤规则,扫描只包含哪些组件 //componentScan value制定要扫描的包 //FilterType.ANNOTATION:按照注解 public class MainConfig { //给容器中注册一个bean;类型为返回值的类型,id默认使用方法名作为id @Bean public Person person() { return new Person("lisi", 20); } }
MyTypeFilter.class
public class MyTypeFilter implements TypeFilter { /** * * @param metadataReader 当前正在扫描的类的信息 * @param metadataReaderFactory 可以获取到其他任何类信息的 * @return * @throws IOException */ @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //获取当前类注解的信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //获取当前正在扫描的类的类信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前类资源信息(类的路径) Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName(); System.out.println("----->>" + className); // if (className.contains("er")) {return true;} return false; } }
结果:
2 @ Import 添加 @scope 调整作用域
MainConfig2
//满足当前条件,这个类中配置的所以bean注册才能生效 //@Conditional({LinuxCondition.class}) @Configuration //导入组件,id默认是组件的全类名 @Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) public class MainConfig2 { //默认是单实例的 //@scope 调整作用域 //prototype(多实例) singleton(默认的)ioc启动会调用方法创建对象放到ioc容器中 request(同一次请求创建一个实例) session(同一个session创建一个实例) /** * 懒加载: * 单实例bean:默认在容器启动的时候创建对象 * 懒加载:容器启动不加载。第一次使用(获取)bean创建对象,并进行初始化 * @return */ // @Scope("prototype") @Lazy @Bean(value = "person") public Person person(){ System.out.println("给容器添加person"); return new Person("张三", 25); } /** * @conditional({condition}) :按照一定的条件进行判断,满足条件给容器中注册bean * 如果是Windows 注册bill * 如果是Linux 注入 linas */ @Conditional({WindowsCondition.class}) @Bean("bill") public Person person01() { return new Person("Bill Gates", 62); } @Bean("linas ") public Person person02() { return new Person("linas", 70); } /** * 给容器中注册组件 * 1》包扫描+组件标注注解(@Controller @Service @Repository @Component [自己写的类]) * 2》@Bean [导入的第三方包里面的组件] * 3》@Import [快速给容器中导入一个组件] * 1)@Import(要导入到容器中的组件):容器中就会自动注册这个组件,id默认是全类名 * 2)ImportSelector:返回需要导入的组件的全类名数组; * 3)ImportBeanDefinitionRegistrar: 手动注册bean到容器中 * 4》使用Spring提供的FactoryBean(工厂bean) * 1)默认获取奥的是工厂bean调用getObject创建的对象 * 2)要获取工厂bean本身,我们需要给id前面加一个& * &colorFactoryBean * */ @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); } }
MyImportSelector.class
//自定义逻辑返回需要导入的组件 public class MyImportSelector implements ImportSelector { //返回值,就是到导入到容器中的组件全类名 //AnnotationMetadata:当前标注@Import注解的类的所有注解信息 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { //importClassMetadata // return new String[]{"com.bean.Blue","com.bean.Yellow"}; } }
MyImportBeanDefinitionRegistrar.class
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * * @param importingClassMetadata 当前类的注解信息 * @param registry BeanDefinition注册类 * 把所以需要添加到容器中的bean:调用BeanDefinitionRegistry.registerBeanDefinition手工注册进来 */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean red = registry.containsBeanDefinition("com.bean.Red"); if (red) { //制定Bean定义信息(Bean的类型,Bean) RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class); //注册一个Bean,指定bean名 registry.registerBeanDefinition("rainBow", rootBeanDefinition); } } }