Spring之底层架构核心概念解析

目录

一、BenDefinition

二、Spring定义Bean的方式

三、BeandefinitionReader

四、AnnotatedBeandefinitionReader

五、XmlBeanDefinitionReader

六、ClassPathBeanDefinitionScanner

七、BeanFactory

八、ApplicationContext

1、国际化

2、资源加载

3、获取运行环境

4、事件发布

九、类型转换

1、PropertyEditor

2、ConversionService

3、TypeConverter

4、OrderComparator

十、MetadataReader、ClassMetadata、AnnotationMetadata

十一、ExcludeFilter和IncludeFiler


一、BenDefinition

Beandefinition表示Bean的定义,Spring源码中它是一个接口,Beandefinition中存在很多属性用来描述Bean的特点:

class:表示Bean的类型

scope:表示Bean的作用域,单例或多例等

lazyInit:表示是Bean是否是懒加载

initMethodName:表示Bean初始化时要执行的方法

destroyMethodName:表示Bean销毁时需要执行的方法

二、Spring定义Bean的方式

1、声明式定义Bean:<bean/>,@Bean,@Component(@Service,@Controller)

2、编程式定义Bean:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//用BeanDefinitionBuilder工具生成beanDefinition对象
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
//beanDefinition对象指定Bean类型
beanDefinition.setBeanClass(UserService.class);
//beanDefinition对象指定Bean的作用域,等等很多属性可以定义
beanDefinition.setScope("prototype");
//光定义一个Bean,还需要放入容器中才能生效
context.registerBeanDefinition("userService",beanDefinition);

三、BeandefinitionReader

BeandefinitionReader是Beandifinition的读取器,相当于Spring的基础设施,在源码中应用很多。

四、AnnotatedBeandefinitionReader

AnnotatedBeandefinitionReader可以直接把某个类转换为BeanDefinition,而后放入容器中成为一个Bean,并且会解析该类上的注解。

/**AnnotatedBeanDefinitionReader把对象变成BeanDefinition,
放到容器中,这个对象就会成为一个Bean*/
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);
annotatedBeanDefinitionReader.register(UserService.class);

五、XmlBeanDefinitionReader

XmlBeanDefinitionReader可以解析<bean/>标签

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");

六、ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner是扫描器,它的作用和BeanDefinition类似,它可以扫描某个包路径,对扫描到的类进行解析。

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
context.refresh();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
//扫描com.qual路径,而后就可以去获取该路径下相应的Bean了
scanner.scan("com.qual");
//比如获取UserService的Bean
context.getBean("userservice");

七、BeanFactory

BeanFactory表示Bean工厂,很明显BeanFactory会负责创建Bean,并且提供获取Bean的API,而ApplicationContext是BeanFactory的一种,ApplicationContext继承了ListableBeanFactory和HierarchicalBeanfactory接口,这两个接口都继承了BeanFactory,所以也可以认为ApplicationContext继承了BeanFactory。

/**EnvironmentCapable:表示获取环境变量
ListableBeanFactory:拥有获取beanNames的功能
HierarchicalBeanFactory:拥有获取父BeanFactory的功能
MessageSource:表示国际化
ApplicationEventPublisher:表示事件发布
ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等)
*/
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {}
 
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(UserService.class);
beanFactory.registerBeanDefinition("userService",beanDefinition);
beanFactory.getBean("userService");

八、ApplicationContext

ApplicationContext这个接口相当于继承了BeanFactory,它有两个比较重要的实现类:AnnotationConfigApplicationContext和ClassPathxmlApplicationContext。

1、国际化

先定义一个MessageSource

 @Bean
 public MessageSource messageSource() {
      ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
      //message是文件的名字
      messageSource.setBasename("message");
      return messageSource;
 }
@Component
public class UserService implements ApplicationContextAware{
    @Autowired
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void test(){
        //文件messages_en.properties中有key=a,则message就是对于的值a
        String message = applicationContext.getMessage("key", null, new Locale("en"));
    }
}

2、资源加载

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Resource resource = context.getResource("file://D:\\idea\\UserService.java");
resource.contentLength();

3、获取运行环境

也可以用注解:@PropertySource("classPath:spring.properties")来使得某个properties文件中的参数添加到运行时环境中

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MutablePropertySources propertySources = context.getEnvironment().getPropertySources();

4、事件发布

事件除了发布还需要定义一个事件监听器

//监听事件
@Bean
public ApplicationListener applicationListener(){
    return new ApplicationListener() {
        @Override
        public void onApplicationEvent(ApplicationEvent applicationEvent) {
            System.out.println("接收到了一个事件");
        }
    };
}
@Component
public class UserService implements ApplicationContextAware{
    @Autowired
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    public void test(){
        //发布事件
        applicationContext.publishEvent("123");
        System.out.println("test");
    }
}

九、类型转换

在Spring源码中,有可能需要把String类型转换成其他类型

1、PropertyEditor

它是JDK提供的类型转化工具类。

2、ConversionService

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

3、TypeConverter

它整合了PropertyEditor和ConversionSservice的功能。

4、OrderComparator

OrderComparator是Spring提供的一种比较器,可以根据@Order注解或实现Ordered接口来执行值进行笔记,从而可以进行排序。Spring还提供了一个OrderCompatator的子类AnnotationAwareOrderCompatator,它支持用@Order来指定Order值。

十、MetadataReader、ClassMetadata、AnnotationMetadata

MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader。

public static void main(String[] args) throws IOException{
        //构造元数据读取器的工厂
        SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
        //构造一个MetadataReader
        MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.qual.service.UserService");
        //得到一个ClassMetadata,并获取了类名
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        System.out.println( classMetadata.getClassName());
    }

注意:SimpleMetadataReader去解析类时,使用的时ASM技术。因为Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的类时非常多的,那如果在Spring启动时就把这些全部加载进JVM了,这样不太好,所以使用了ASM技术。

十一、ExcludeFilter和IncludeFiler

这两个Filter是Spring扫描过程中用来过滤的。ExcludeFilter表示排除过滤器,IncluderFiter表示包含过滤器。

FilterType分为:

1、ANNOTATION:表示是否包含某个注解;

2、ASSIGNABLE_TYPE:表示是否是某个类;

3、ASPECTJ:表示是否符合某个AspectJ表达式;

4、REGEX:表示是否符合某个正则表达式;

5、CUSTOM:自定义。

/**一下配置表示扫描com.qual这个包下面的所有类,但是排除UserService类,
也就是就算它上面有@Component注解也不会成为Bean*/
@ComponentScan(value="com.qual",
        excludeFilters = {@ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE,
                classes = UserService.class
        )})
public class AppConfig {

}
/**一下配置表示扫描com.qual这个包下面的所有类,
就算它上面没有@Component注解也会成为Bean*/
@ComponentScan(value="com.qual",
        includerFilters= {@ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE,
                classes = UserService.class
        )})
public class AppConfig {

}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值