BeanDefinition
AnnotatedBeanDefinitionReader
可以解析注解是:@Bean、@Conditional、@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description,生成AnnotateBeanBeanDefinition
@Lazy
@Component
public class Tank {
public Tank(){
System.out.println("Tank初始化");
}
}
/**
* 测试注解bean定义读取器
*/
@Test
public void testAnnotatedBeanDefinitionReader() {
//1.初始化IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//2.在1中已经完成。初始化(注解)bean读取器,同时注册Spring内部原始bean,原始bena用于应用程序bean的解析
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(applicationContext);
//3.利用给定的 Class对象,从类的注解中获取其元数据,组装beanDefinition对象,并向IOC容器注册
annotatedBeanDefinitionReader.registerBean(Tank.class);
//4.刷新IOC容器,完成对象实例化
applicationContext.refresh();
Tank tank = applicationContext.getBean("tank", Tank.class);
System.out.println(tank);
}
XmlBeanDefinitionReader
ClassPathBeanDefinitionScanner
一个扫描器,与BeanDefinitionReader功能类似,可以进行包路径扫描,对使用@Component注解的类进行解析,生成ScannedGenericBeanDefinition
Spring在初始化时,默认在IncludeFilter中添加@Componet。所以在后续扫描根据IncludeFilter进行判断
/**
* 测试注解bean定义扫描器
*/
@Test
public void testClassPathBeanDefinitionScanner() {
//1.初始化IOC容器
applicationContext = new AnnotationConfigApplicationContext();
//2.在1中已经完成。注册默认注解过滤器(即:可以识别[@Component、@Repository、@Service、@Controller]
ClassPathBeanDefinitionScanner classPathBeanDefinitionScanner = new ClassPathBeanDefinitionScanner(applicationContext);
//3.扫描指定路径下.class文件,并将带有@Component注解的.class文件,组装beanDefinition对象,并向IOC容器注册
classPathBeanDefinitionScanner.scan("com.masterlu.ioc.entity");
applicationContext.refresh();
Tank tank = applicationContext.getBean("tank", Tank.class);
System.out.println(tank);
}
ExcludeFilter和IncludeFilter
两个Filter是Spring扫描过程中用来过滤的。ExcludeFilter表示排除过滤器,IncludeFilter表示包含过滤器
//表示扫描com.masterlu包下面的所有类,但是排除UserService类,也就是就算它上面有@Component注解也不会成为Bean
@ComponentScan(value = "com.masterlu",
excludeFilters = {@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = UserService.class)}.)
public class AppConfig {
}
//就算UserService类上没有@Component注解,它也会被扫描成为一个Bean
@ComponentScan(value = "com.masterlu",
includeFilters = {@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = UserService.class)})
public class AppConfig {
}
FilterType分为:
1. ANNOTATION:表示是否包含某个注解
2. ASSIGNABLE_TYPE:表示是否是某个类
3. ASPECTJ:表示否是符合某个Aspectj表达式
4. REGEX:表示是否符合某个正则表达式
5. CUSTOM:自定义
Spring在初始化时,默认在IncludeFilter中添加@Componet。所以在后续扫描根据IncludeFilter进行判断
BeanFactory
拥有很多功能:
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,拥有了自动装配的功能
15. **DefaultListableBeanFactory**:继承了AbstractAutowireCapableBeanFactory,实现了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大
ApplicationContext
ApplicationContext是个接口,实际上也是一个BeanFactory,不过比BeanFactory更加强大,比如:
- HierarchicalBeanFactory:拥有获取父BeanFactory的功能
- ListableBeanFactory:拥有获取beanNames的功能
- ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等)
- EnvironmentCapable:可以获取运行时环境(没有设置运行时环境功能)
- ApplicationEventPublisher:拥有广播事件的功能(没有添加事件监听器的功能)
-
AnnotationConfigApplicationContext
- ConfigurableApplicationContext:继承了ApplicationContext接口,增加了,添加事件监听器、添加BeanFactoryPostProcessor、设置Environment,获取ConfigurableListableBeanFactory等功能
- AbstractApplicationContext:实现了ConfigurableApplicationContext接口
- GenericApplicationContext:继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口,拥有了所有ApplicationContext的功能,并且可以注册BeanDefinition,注意这个类中有一个属性(DefaultListableBeanFactory beanFactory)
- AnnotationConfigRegistry:可以单独注册某个类为BeanDefinition(可以处理该类上的@Configuration注解,可以处理@Bean注解),同时可以扫描
- AnnotationConfigApplicationContext:继承了GenericApplicationContext,实现了AnnotationConfigRegistry接口,拥有了以上所有的功能
MetadataReader、ClassMetadata、AnnotationMetadata
Spring中需要去解析类的信息。比如类名、方法、类上的注解,这些都可以称之为类的元数据,
Spring中对类的元数据做了抽象,并提供了一些工具类。
MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader
SimpleMetadataReader去解析类时,使用的ASM技术(不需要加载类,就可以解析)。保持JVM使用类时,再加载特性 。 ```java @Service puliic class UserService{
}
public class Test {
public static void main(String[] args) throws IOException {
SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
// 构造一个MetadataReader
MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.masterlu.service.UserService");
// 得到一个ClassMetadata,并获取了类名
ClassMetadata classMetadata = metadataReader.getClassMetadata();
System.out.println(classMetadata.getClassName());
// 获取一个AnnotationMetadata,并获取类上的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//判断是否使用了指定注解
System.out.protintln(annotationMetadata.hasMetaAnnotation(Component.class.getName()));//true。自动识别注解继承
System.out.protintln(annotationMetadata.hasAnnotation(Component.class.getName()));//false
for (String annotationType : annotationMetadata.getAnnotationTypes()) {
System.out.println(annotationType);
}
}
}
BeanDefinition只是元数据的一部分。
<a name="ZqBNS"></a>
# 其他功能
<a name="p9cX1"></a>
## 类型转换
在Spring源码中,有可能需要把String转成其他类型,所以在Spring源码中提供了一些技术来更方便的做对象的类型转化<br />另外,使用applicationContext.getBean("beanName",Class),第二个参数传递类型。1.为了泛型,2.也是主要的作用,Spring通过beanName获取到对象实例后,会进行实例转换。将实例转换成指定的Class类型。就是利用的类型转换
<a name="F4wdW"></a>
### PropertyEditor
JDK中提供的类型转化工具类
```java
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);
//本质就是手动生成对象,并使用set方法赋值
向Spring中注册PropertyEditor(Spring和JDK结合使用)
//Spring和JDK结合使用。本质,预先定义转换过程
@Bean
public CustomEditorConfigurer customEditorConfigurer() {
CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
Map<Class<?>, Class<? extends PropertyEditor>> propertyEditorMap = new HashMap<>();
//表示StringToUserPropertyEditor可以将String转化成User类型,在Spring源码中,如果发现当前对象是String,而需要的类型是User,就会使用该PropertyEditor来做类型转化
propertyEditorMap.put(User.class, StringToUserPropertyEditor.class);// 此处使用的上面JDK提供实现类
customEditorConfigurer.setCustomEditors(propertyEditorMap);
return customEditorConfigurer;
}
@Component
public class UserService {
@Value("xxx")
private User user;
public void test() {
System.out.println(user);
}
}
ConversionService
仅使用Spring中提供的类型转化服务,它比PropertyEditor更强大
public class StringToUserConverter implements ConditionalGenericConverter {
//设置使用场景:例如:String-->User
@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;
}
@Component
public class UserService {
@Value("xxx")
private User user;
public void test() {
System.out.println(user);
}
}
TypeConverter
整合了PropertyEditor(JDK方式)和ConversionService(Spring方式)的功能,是Spring内部用的
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
//jdk模式转换
typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
//Spring模式转换
typeConverter.setConversionService(conversionService);
//手工,展示使用
User value = typeConverter.convertIfNecessary("1", User.class);
System.out.println(value);
国际化
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
你可以在你任意想要进行国际化的地方使用该MessageSource。 同时,因为ApplicationContext也拥有国家化的功能,所以可以直接这么用:
context.getMessage(“test”, null, new Locale(“en”))
事件发布
//事件监听器
@Bean
public ApplicationListener applicationListener() {
return new ApplicationListener() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("接收到了一个事件");
}
};
}
//发布事件
context.publishEvent("kkk");
获取运行时环境
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//操作系统级别
Map<String, Object> systemEnvironment = context.getEnvironment().getSystemEnvironment();
System.out.println(systemEnvironment);
System.out.println("=======");
//java -D 指定的系统变量
Map<String, Object> systemProperties = context.getEnvironment().getSystemProperties();
System.out.println(systemProperties);
System.out.println("=======");
//获取:@PropertySource注解标记的变量
MutablePropertySources propertySources = context.getEnvironment().getPropertySources();
System.out.println(propertySources);
System.out.println("=======");
//获取环境变量功能
System.out.println(context.getEnvironment().getProperty("NO_PROXY"));
System.out.println(context.getEnvironment().getProperty("sun.jnu.encoding"));
System.out.println(context.getEnvironment().getProperty("name"));
可以利用,@PropertySource(“classpath:spring.properties”)
来使得某个properties文件中的参数添加到运行时环境中
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "common.thread.pool")
@PropertySource("classpath:threadPool.properties")
public class ThreadPoolProperties {
private int corePoolSize;
private int maxPoolSize;
private int keepAliveTime;
private String threadNamePrefix;
private int queueCapacity;
}
资源加载
ApplicationContext还拥有资源加载的功能,比如,可以直接利用ApplicationContext获取某个文件的内容
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Resource resource = context.getResource("file://D:\\IdeaProjects\\spring-framework\\test\\src\\main\\java\\com\\luban\\entity\\User.java");
System.out.println(resource.contentLength());
Resource resource1 = context.getResource("https://www.baidu.com");
System.out.println(resource1.contentLength());
System.out.println(resource1.getURL());
Resource resource2 = context.getResource("classpath:spring.xml");
System.out.println(resource2.contentLength());
System.out.println(resource2.getURL());
Resource[] resources = context.getResources("classpath:com/masterlu/*.class");
for (Resource resource : resources) {
System.out.println(resource.contentLength());
System.out.println(resource.getFilename());
}