美文网首页
spring几个核心概念

spring几个核心概念

作者: 净土_0342 | 来源:发表于2021-02-22 22:46 被阅读0次

    1 BeanDefinition

    spring里面一个bean的定义类就是BeanDefinition,在spring中,我们可以如下定义一个Bean:

    1. <bean/>
    2. @Bean
    3. @Component(@Service, @Controller)

    还有可以通过Spring提供给我们的API的编程式地定义一个BeanDefinition:

    private static void beanDefinitionTest() {
       AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
       AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
       beanDefinition.setBeanClass(AppConfig.class);
       beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
       applicationContext.registerBeanDefinition("appConfig", beanDefinition);
       beanDefinition.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE); // 设置自动装配模型
       // 根据BeanDefinition来产生bean对象
       applicationContext.refresh();
       System.out.println(applicationContext.getBean("appConfig"));
    }
    

    2 BeanDefinitionReader

    从名字来看,BeanDefinitionReader就是读取BeanDefinition的工具,BeanDefinition是一个接口,具体的从哪里读取就要看他具体的实现类:

    image-20210124223015083

    2.1 XmlBeanDefinition

    XmlBeanDefinitionReader就是从读取Xml里面的配置,然后生成BeanDefinition.

    private static void xmlBeanDefinitionTest() {
       AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
       XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(applicationContext);
       int i = reader.loadBeanDefinitions("spring.xml");
       System.out.println(i);
    }
    

    2.2 AnnotatedBeanDefinitionReader

    AnnotatedBeanDefinitionReader是解析一个类其他的注解,然后生成一个AnnotatedBeanDefinition.

    private static void annotatedBeanDefinitionTest() {
       AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
       AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(applicationContext);
       // 不管Person.class这个类上面有没有Component注解都会解析其他注解,比如@Scope和@Lazy等
       reader.register(Person.class);
       applicationContext.refresh();
       System.out.println(applicationContext.getBean("person"));
    }
    

    2.3 ClassPathBeanDefinitionScanner

    ClassPathBeanDefinitionScanner是指定一个包路径,然后进行扫描,获取beanDefinition,接着用refresh就可以把实例创建出来。

    这里可以扫描@Service和@Component等注解,但是不能扫描@Bean注解

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

    2.4 BeanFactory

    Spring中比较核心的是BeanFactory的实现类是DefaultListableBeanFactory

    我们先从DefaultListableBeanFactory的继承结构说起

    image-20210201221042339
    1. AliasRegistry:支持别名功能,一个名字可以对应多个别名,主要的方法如下:

      image-20210201221324760
      • 注册别名
      • 删除别名
      • 判断这个名字是否别名
      • 指定名字获取别名

      他的一个简单地实现类是:SimpleAliasRegistry(现在不做过多的解读)

    2. BeanDefinitionRegistry:可以注册、保存、移除、获取某个BeanDefinition

      image-20210201230046563
    3. BeanFactory:Bean工厂,可以根据某个bean的名字、或类型、或别名获取某个Bean对象

      image-20210201230029923
    4. SingletonBeanRegistry:可以直接注册、获取某个单例Bean

      [图片上传失败...(image-528ee7-1614005134434)]

    5. DefaultSingletonBeanRegistry:它是一个类,实现了SingletonBeanRegistry接口,拥有了直接注册、获取某个单例Bean的功能

      image-20210201225910027
    6. HierarchicalBeanFactory:在BeanFactory的基础上,添加了获取父BeanFactory的功能

      image-20210201225851202

      有一种场景,如果你在beanFactory里面获取不到一个bean,他会自动从他父beanFactory里面获取这个bean

    7. ListableBeanFactory:在BeanFactory的基础上,增加了其他功能,可以获取所有BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的Bean}的映射关系

      image-20210201225750651
    8. FactoryBeanRegistrySupport:支持了FactoryBean的功能

      image-20210201230321107
    9. ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,添加了设置父BeanFactory、类加载器(表示可以指定某个类加载器进行类的加载)、设置Spring EL表达式解析器(表示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示该BeanFactory可以进行类型转化)、可以添加BeanPostProcessor(表示该BeanFactory支持Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能

    10. AbstractBeanFactory:实现了ConfigurableBeanFactory接口,继承了FactoryBeanRegistrySupport,这个BeanFactory的功能已经很全面了,但是不能自动装配和获取beanNames

    11. ConfigurableListableBeanFactory:继承了ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactory

    12. AbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory,拥有了自动装配的功能

    13. DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory,实现了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大

    通过以上分析,我们可以知道,通过DefaultListableBeanFactory我们可以做很多事情,比如:

    AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
    beanDefinition.setBeanClass(User.class);
    
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    
    // 注册BeanDefinition
    beanFactory.registerBeanDefinition("user", beanDefinition);
    // 注册别名
    beanFactory.registerAlias("user", "user1");
    // 注册BeanPostProcessor
    beanFactory.addBeanPostProcessor(new LubanBeanPostProcessor());
    
    // 获取Bean对象
    System.out.println(beanFactory.getBean("user1"));
    // 根据类型获取beanNames
    System.out.println(beanFactory.getBeanNamesForType(User.class));
    

    2.5 ApplicationContext

    首先ApplicationContext是个接口,可以把它理解为一个特殊的BeanFactory

    image-20210222215923730
    1. HierarchicalBeanFactory:拥有获取父BeanFactory的功能

      System.out.println(applicationContext.getParentBeanFactory());
      
    2. ListableBeanFactory:拥有获取beanNames的功能

      System.out.println(applicationContext.getBeanDefinitionNames());
      
    3. ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等)

      Resource resource = applicationContext.getResource("spring.xml");
      System.out.println(resource.contentLength());
      
    4. EnvironmentCapable:可以获取运行时环境(没有设置运行时环境功能)

      ConfigurableEnvironment environment = applicationContext.getEnvironment();
      System.out.println(environment.getSystemProperties());
      System.out.println(environment.getSystemEnvironment());
      
    5. ApplicationEventPublisher:拥有广播事件的功能(没有添加事件监听器的功能)

      applicationContext.publishEvent("xxx");
      
    6. MessageSource:拥有国际化功能

      System.out.println(applicationContext.getMessage("test", null, new Locale("")));
      

    2.6 AnnotationConfigApplicationContext

    image-20210222221514521
    1. ConfigurableApplicationContext:继承了ApplicationContext接口,增加了,添加事件监听器、添加BeanFactoryPostProcessor、设置Environment,获取ConfigurableListableBeanFactory等功能
    2. AbstractApplicationContext:实现了ConfigurableApplicationContext接口
    3. GenericApplicationContext:继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口,拥有了所有ApplicationContext的功能,并且可以注册BeanDefinition,注意这个类中有一个属性(DefaultListableBeanFactory beanFactory)
    4. AnnotationConfigRegistry:可以单独注册某个为类为BeanDefinition(可以处理该类上的@Configuration注解,已经可以处理@Bean注解),同时可以扫描
    5. AnnotationConfigApplicationContext:继承了GenericApplicationContext,实现了AnnotationConfigRegistry接口,拥有了以上所有的功能

    3 类型转换

    3.1 PropertyEditor

    JDK提供的一个类型转换器

    public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {
    
        @Override
        public void setAsText(String text) throws IllegalArgumentException {
            User user = new User();
            user.setName(text);
            this.setValue(user);
        }
    }
    

    普通是这样来使用的

    StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
    propertyEditor.setAsText("1");
    User value = (User) propertyEditor.getValue();
    System.out.println(value);
    

    如何向Spring中注册PropertyEditor:

    @Bean
    public CustomEditorConfigurer customEditorConfigurer() {
        CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
        Map<Class<?>, Class<? extends PropertyEditor>> propertyEditorMap = new HashMap<>();
        propertyEditorMap.put(User.class, StringToUserPropertyEditor.class);
        customEditorConfigurer.setCustomEditors(propertyEditorMap);
        return customEditorConfigurer;
    }
    

    假设现在有如下Bean:

    @Component
    public class UserService {
    
        @Value("true")
        User test;
    
        public void test() {
            System.out.println(test);
        }
    }
    

    那么test属性就能正常的完成属性赋值

    3.2 ConversionService

    Spring中提供的类型转化服务,它比PropertyEditor更强大

    public class StringToUserConverter implements ConditionalGenericConverter {
    
        @Override
        public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
            return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);
        }
    
        @Override
        public Set<ConvertiblePair> getConvertibleTypes() {
            return Collections.singleton(new ConvertiblePair(String.class, User.class));
        }
    
        @Override
        public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
            User user = new User();
            user.setName((String)source);
            return user;
        }
    }
    
    DefaultConversionService conversionService = new DefaultConversionService();
    conversionService.addConverter(new StringToUserConverter());
    User value = conversionService.convert("1", User.class);
    System.out.println(value);
    

    如何向Spring中注册ConversionService:

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

    3.3 TypeConverter

    整合了PropertyEditor和ConversionService的功能,是Spring内部用的

    SimpleTypeConverter typeConverter = new SimpleTypeConverter();
    typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
    //typeConverter.setConversionService(conversionService);
    User value = typeConverter.convertIfNecessary("1", User.class);
    System.out.println(value);
    

    相关文章

      网友评论

          本文标题:spring几个核心概念

          本文链接:https://www.haomeiwen.com/subject/scrlfltx.html