03Spring底层架构核心概念解析
为了感谢罕哥对我工作的帮助,特此记录下学习过程,期待成为和罕哥一样优秀的人
时间:2024.7.13
内容:spring源码课程3学习记录
一、BeanDefinition
BeanDefinition表示Bean的定义,BeanDefinition中存在很多属性用来描述一个Bean的特点
class:表示Bean类型
scope:表示Bean的作用域(单例/原型)
lazyInit:表示Bean是否是懒加载
initMethodName:表示Bean初始化时要执行的方法
destroyMethodName:表示Bean销毁时要执行的方法
........
二、在Spring中,定义Bean的方式
声明式定义:
1、
2、@Bean
3、@Component(@Service,@Controller)
编程式定义:
直接通过BeanDefinition,此处就是Spring源码定义一个Bean的实现过程
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); beanDefinition.setBeanClass(UserService.class); beanDefinition.setScope("prototype"); //把beanDefinition注册到容器中 context.registerBeanDefinition("userService",beanDefinition); UserService userService = (UserService)context.getBean("userService"); userService.test();
三、Spring内部的组件
下面的组件在Spring中使用的很少,但是在源码中使用的很多,学习有利于理解源码
1、AnnotatedBeanDefinitionReader
可以直接把某个类转换为BeanDefinition,并读取解析类的注解。就是BeanDefiniton读取器。把读到的BeanDefinition存到容器中
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context); //将UserService.class解析为BeanDefinition annotatedBeanDefinitionReader.register(UserService.class); System.out.println(context.getBean("userService"));
2、XmlBeanDefinitionReader
可以解析标签
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context); xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
3、ClassPathBeanDefinitionScanner
扫描器,和BeanDefinitionReader类似,对某个包路径就行扫描,对扫描的类进行解析,如果存在@Component注解,就会把这个类解析为一个BeanDefinition
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.refresh(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); int i = scanner.scan("org.com.zhuyn"); System.out.println(context.getBean("userService"));
四、ApplicationContext与BeanFactory
ApplicationContext继承了BeanFactory,除此之外还继承了别的
ApplicationEnventPublisher:事件发布器
EnvironmentCapable:获取环境变量的功能
MessageSource:进行国际化的功能
ResourcepatternResolver:解析某些资源的功能
因此,当我们使用applicationContext.getBean("xxx")的时候,本质上是使用的DefaultListableBeanFactory来获取的。
1、ResourcepatternResolver
(1)拿文件资源
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); Resource resource = context.getResource("file://C:\\Usersxxxxxxxxx""); System.out.println(resource.contentLength());
(2)拿url
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); Resource resource = context.getResource("https://www.baidu.com"); System.out.println(resource.contentLength()); System.out.println(resource.getURL());
这里的Resource可以拿很多种资源。
2、ApplicationEnventPublisher
在工作当中可以直接定义一个事件发布器、
@Component public class UserService { private ApplicationEventPublisher applicationEventPublisher; }
也可以使用applicationContext自带的事件发布器
@Component public class UserService { @Autowired private ApplicationContext context; public void test(){ context.publishEvent("hello"); System.out.println("test"); } }
事件监听器
@ComponentScan("org.com.zhuyn") public class AppConfig { @Bean public ApplicationListener applicationListener(){ return new ApplicationListener() { @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { System.out.println("发布了一个事件"+applicationEvent); } }; } }
五、类型转化
1、PropertyEditor
把字符串转换成user对象。
类型转换器
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); } }
类型转换器的使用
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor(); propertyEditor.setAsText("xiaoming"); User user = (User) propertyEditor.getValue(); System.out.println(user.getName());
在spring内部也使用到了类型转换,例如当我们使用这个
UserService userservice = context.getBean("userService",UserService.class)
我们传一个string类型,得到一个UserService类型的对象。
2、ConversionService
3、TypeConverter
六、比较器
可以根据@Order注解或实现Ordered接口来执行值进行比较,从而可以进行排序。
Ordered接口实现方法:
1、在类上实现Ordered接口
2、使用OrderComparator构建比较器
类A
public class A implements Ordered { @Override public int getOrder() { return 1; } }
类B
public class B implements Ordered { @Override public int getOrder() { return 10; } }
应用:
A a = new A(); B b = new B(); OrderComparator comparator = new OrderComparator(); System.out.println(comparator.compare(a, b));//-1 a大为1,b大为-1 List list = new ArrayList(); list.add(a); list.add(b); //按order值升序排序 list.sort(comparator); System.out.println(list);//[org.com.zhuyn.Service.A@2f2c9b19, org.com.zhuyn.Service.B@31befd9f]
@Order注解实现方法
Spring提供了OrderComparator的子类:AnnotationAwareOrderComparator,它支持使用@Order来指定order值
类C
@Order(1) public class C { }
类D
@Order(10) public class D { }
应用
C c = new C(); D d = new D(); AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator(); System.out.println(comparator.compare(c,d));//-1
七、类的元数据
在Spring中需要去解析类的信息,比如类名,类中的方法,类上的注解,这些都可以称为类的元数据。所以Spring中对类的元数据做了抽象,并提供了一些工具类。
1、MetaDataReader(类的元数据读取器)
解析一个类,得到类的所有信息。AnnotatedBeanDefinitionReader 只读取了类的注解而MetaDataReader读取了一个类的所有信息,包括类的注解,类继承了什么,类实现了哪些方法.....等等。
MetaDataReader是一个接口,默认实现类为SimpleMetadataReader。
SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory(); //构造一个MetaDataReader MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("org.com.zhuyn.Service.UserService"); //得到一个ClassMetaData,并获取类名 ClassMetadata classMetadata = metadataReader.getClassMetadata(); System.out.println(classMetadata.getClassName()); //获取接口名字,结果为一个数组 System.out.println(classMetadata.getInterfaceNames()[0]); //类上注解的信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); for(String annotionMetadata:annotationMetadata.getAnnotationTypes()){ System.out.println(annotionMetadata); }
八、过滤器
1、excludeFilters
排除类名为UserService的类,就算她上面有@component注解,也不会成为Bean
@ComponentScan(value = "org.com.zhuyn", excludeFilters = {@ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = UserService.class ) }) public class AppConfig { }
2、includeFilters
就算UserService类上没有@Component注解,它也会被扫描成为一个Bean。
@ComponentScan(value = "org.com.zhuyn", includeFilters = {@ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = UserService.class )}) public class AppConfig{ }
九、FactoryBean
可以通过这个来自己创建一个Bean