阅读Spring之前需要了解的部分基础组件

一、BeanDefinition:Class可以用来描述一个类的属性和方法等等其他信息,BeanDefintion可以描述spring的bean信息,比如beanClass,scope、lazyInit,autowireMode以及属性和方法等等其他信息

我们定义的类标有@Component、@Service、@Controller、@Bean等注解的最终都会先生成一个BeanDefinition,也可以自己通过编程式的方式声明一个BeanDefinition,然后注册到容器中,从而生成bean,如下代码

        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        //编程式的方式声明一个Bean通过定义BeanDefinition的形式
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setScope("singleton");
//        beanDefinition.setBeanClass(A.class);
        //通过使用setBeanClass传入类名.class或者setBeanClassName传入类的全路径+类名
        beanDefinition.setBeanClassName("com.xqc.A");
        //懒加载=false
        beanDefinition.setLazyInit(false);
        //注册到容器中,然后生成一个bean
        applicationContext.registerBeanDefinition("a",beanDefinition);

        System.out.println(applicationContext.getBean("a"));

实现或者继承此接口的类或者接口名称

类名:AbstractBeanDefinition、RootBeanDefinition、GenericBeanDefinition、ScannedGenericBeanDefinition

接口名:AnnotatedBeanDefinition

二、BeanDefinitionReader:BeanDefinition的读取器,主要有AnnotatedBeanDefinitionReaderXmlBeanDefinitionReader

AnnotatedBeanDefinitionReader:主要解析通过注解方式定义的bean,
然后生成BeanDefinition,可以解析的@Conditional,@Scope、@Lazy、@Primary、
@DependsOn、 @Role、@Description

        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        //Annotated方式读取
        AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(applicationContext);
        //C本身是一个很普通的类,通过BeanDefinitionReader将C.class解析为BeanDefinition
        annotatedBeanDefinitionReader.register(C.class);
        System.out.println(applicationContext.getBean("c"));

XmlBeanDefinitionReader:主要读取xml定义的bean,然后生成BeanDefinition,
例如在xml里通过</bean>标签的bean

        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        //xml方式读取
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
        xmlBeanDefinitionReader.loadBeanDefinitions("applicationContext.xml");
        System.out.println(applicationContext.getBean("b"));

 三、ClassPathBeanDefinitionScanner:扫描器,但是它的作用和BeanDefinitionReader类似,它可以 进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component 注解,那么就会把这个类解析为一个BeanDefinition。

        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.refresh();
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(applicationContext);
        //设置扫描的包
        scanner.scan("com.xqc");
        System.out.println(applicationContext.getBean("d"));

四、BeanFactory:bean工厂,可以创建和获取bean,spring容器的顶级接口,ApplicationContext也是继承了它的。它有一个非常重要的类DefaultListableBeanFactory,也是非常核心的。

 它实现了很多接口,表示,它拥有很多功能:

1. AliasRegistry:支持别名功能,一个名字可以对应多个别名
2. BeanDefinitionRegistry:可以注册、保存、移除、获取某个BeanDefinition
3. BeanFactory:Bean工厂,可以根据某个bean的名字、或类型、或别名获取某个Bean对象
4. SingletonBeanRegistry:可以直接注册、获取某个 单例 Bean
5. SimpleAliasRegistry:它是一个类,实现了AliasRegistry接口中所定义的功能,支持别名功能
6. ListableBeanFactory:在BeanFactory的基础上,增加了其他功能,可以获取所有
BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类
型获取{类型:对应的Bean}的映射关系
7. HierarchicalBeanFactory:在BeanFactory的基础上,添加了获取父BeanFactory的功能
8. DefaultSingletonBeanRegistry:它是一个类,实现了SingletonBeanRegistry接口,拥有了直
接注册、获取某个 单例 Bean的功能 9. ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,
添加了设置父BeanFactory、类加载器(表示可以指定某个类加载器进行类的加载)、设置
Spring EL表达式解析器(表示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示
该BeanFactory可以进行类型转化)、可以添加BeanPostProcessor(表示该BeanFactory支持
Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能
10. FactoryBeanRegistrySupport:支持了FactoryBean的功能
11. AutowireCapableBeanFactory:是直接继承了BeanFactory,在BeanFactory的基础上,支持
在创建Bean的过程中能对Bean进行自动装配
12. AbstractBeanFactory:实现了ConfigurableBeanFactory接口,继承了
FactoryBeanRegistrySupport,这个BeanFactory的功能已经很全面了,但是不能自动装配和
获取beanNames
13. ConfigurableListableBeanFactory:继承了ListableBeanFactory、
AutowireCapableBeanFactory、ConfigurableBeanFactory
14. AbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了
AutowireCapableBeanFactory,拥有了自动装配的功能

五、ApplicationContext:ApplicationContext继承了EnvironmentCapable、ListableBeanFactory、HierarchicalBeanFactory、 MessageSource、ApplicationEventPublisher、 ResourcePatternResolver 6个接口。

如图

 而其中ListableBeanFactory和HierarchicalBeanFactory又继承了BeanFactory,所有ApplicationContext也是BeanFactory的一种,拥有BeanFactory的所有功能,但是它比BeanFactory功能又更强大些,主要是它又继承了其它接口,所以功能更丰富些。比如国际化、事件发布、获取环境变量等等。

1、MessageSource国际化

 

 需要先定义一个MessageSource

    @Bean
    public MessageSource messageSource(){
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages");
        return messageSource;
    }

 业务使用

输出结果 

2、ResourcePatternResolver资源加载

①读取本地文件:applicationContext.getResource("file://文件路径")

②读取网络文件:applicationContext.getResource("https://www.baidu.com/");

③ 读取本地配置文件:applicationContext.getResource("classpath:applicationContext.xml")

 3、EnvironmentCapable获取运行时环境参数
获取系统环境变量
applicationContext.getEnvironment().getSystemEnvironment();
获取JVM运行时参数(或者通过-D设置的参数)
applicationContext.getEnvironment().getSystemProperties();
包含和系统环境变量和JVM运行时参数
applicationContext.getEnvironment().getPropertySources();

也可以使用@PropertySource("classpath:spring.properties")读取配置文件的值

4、ApplicationEventPublisher事件发布

继承ApplicationEvent类

 实现ApplicationListener接口

使用ApplicationContext发布事件

5、类型转化

1)JDK自带的类型转换工具PropertyEditor

新建User对象

 实现PropertyEditor,因为PropertyEditorSupport已经实现了该接口,功能已经比较强大,我们可以继承PropertyEditorSupport,

测试,因为用的是jdk自带的,所以跟Spring没有关系

 输出结果 

 2)利用Spring将PropertyEditor注入到容器中,如果我们只是这样写,不加类型转换,运行代码报错,显然一个字符串是不能转化为User对象的

加入下main的类型转换

 成功输出

 3)使用spring提供的ConversionService,功能比jdk的PropertyEditor强大很多


public class StringToUserConverter implements ConditionalGenericConverter{

    /**
     * 匹配规则
     * @param typeDescriptor 原类型
     * @param typeDescriptor1 要转换的目标类型
     * @return
     */
    @Override
    public boolean matches(TypeDescriptor typeDescriptor, TypeDescriptor typeDescriptor1) {
        return typeDescriptor.getType().equals(String.class) && typeDescriptor1.getType().equals(User.class);
    }

    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        return Collections.singleton(new ConvertiblePair(String.class,User.class));
    }

    @Override
    public Object convert(Object o, TypeDescriptor typeDescriptor, TypeDescriptor typeDescriptor1) {
        User user = new User();
        user.setUserName((String) o);
        return user;
    }
}

功能测试,

但是上面这种方式并没有把ConversionService注册到spring容器中。如何注册到spring容器中呢?可以利用ConversionServiceFactoryBean工具。

    @Bean
    public ConversionServiceFactoryBean serviceFactoryBean(){
        ConversionServiceFactoryBean serviceFactoryBean = new ConversionServiceFactoryBean();
        serviceFactoryBean.setConverters(Collections.singleton(new StringToUserConverter()));
        return serviceFactoryBean;
    }

再利用TypeConverter,他整合了jdk自带的和Spring的,因为在一个项目中,我们可能两种方式都定义到,ApplicationContext两个比较重要的实现类:  AnnotationConfigApplicationContextClassPathXmlApplicationContext

六、比较器,OrderComparator,可以用来根据@Order注解或实现Ordered接口来执行值进行比较,从而可以进行排序。

新建B,C两个类

比较输出,可以看出先输出C,后输出B

 Spring中还提供了一个OrderComparator的子类: AnnotationAwareOrderComparator,它支持用@Order来指定order值

 

 七、BeanPostProcessor,BeanPostProcess表示Bena的后置处理器。有两个方法,是spring提供的一个扩展点,在bean初始化前后做相应的事情。

 八、BeanFactoryPostProcessor,表示Bean工厂的后置处理器,在BeanFactory创建过程中可以做一些事情。

九、FactoryBean,可以动态生成一个bean,与@bean的区别是,通过FactoryBean创建的bean是没有经过完整的生命周期的,只经过了bean初始化后的步骤,任然可以生成代理类的,实现FactoryBean接口的这个bean是经过了完整的bean生命周期。

 十、ExcludeFilter和IncludeFilter,这两个Filter是Spring扫描过程中用来过滤的。ExcludeFilter表示排除过滤器,IncludeFilter表示含过滤器
ExcludeFilter使用:
新建一个类orderService,并且加上@Component注解,使之能成为一个bean。测试可以正常输出 

此时在配置类上加上ExcludeFilter,指定排除的类型和类名 ,再测试查看结果,发现OrderService已经不是一个bean了

FilterType的类型:
FilterType.ANNOTATION 按注解类型排除
FilterType.ASSIGNABLE_TYPE 表示是否是某个类
FilterType.ASPECTJ AspectJ表达式
FilterType.REGEX 正则表示达
FilterType.CUSTOM 自定义规则

在Spring的扫描逻辑中,默认会添加一个AnnotationTypeFilter给includeFilters,表示默认情况下
Spring扫描过程中会认为类上有@Component注解的就是Bean。


IncludeFilter使用:新建一个类StockService,不加任何注解,我们从spring容器中去拿,肯定是拿不到的,但是我通过IncludeFilter配置之后再去拿,没任何问题

输出结果:


 十一、MetadataReader:表示类的元数据读取器,默认实现类SimpleMetadataReader可以很方便的读取类信息,底层主要使用的ASM技术,spring内部就是用的此方法,在扫描生成bean的时候就是用的此方法。为什么要使用ASM技术,Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的 类是非常多的,那如果在Spring启动时就把这些类全部加载进JVM了,这样很不合适,如果我们的工程里面的类非常多,都会被加载进去,那我们的JVM那一套加载机制就没用了
ClassMetadata:表示类的元数据
AnnotationMetadata。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值