目录
四、AnnotatedBeandefinitionReader
六、ClassPathBeanDefinitionScanner
十、MetadataReader、ClassMetadata、AnnotationMetadata
一、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。