长春做网站建设的公司,开发者选项,网站开发答辩难点,永久免费空间网站Spring底层核心组件
BeanDefinition
BeanDefinition表示Bean定义#xff0c;有很多属性用来描述Bean的特点#xff1a; class#xff0c;表示Bean类型 scope#xff0c;表示Bean作用域#xff0c;单例或原型等 lazyInit#xff1a;表示Bean是否是懒加载 initMethod…Spring底层核心组件
BeanDefinition
BeanDefinition表示Bean定义有很多属性用来描述Bean的特点 class表示Bean类型 scope表示Bean作用域单例或原型等 lazyInit表示Bean是否是懒加载 initMethodName表示Bean初始化时要执行的方法 destroyMethodName表示Bean销毁时要执行的方法 还有很多... 定义Bean的方式主要分为两种 申明式定义 1、bean/
2、Bean
3、Component(Service,Controller) 编程式定义 AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);// 生成一个BeanDefinition对象并设置beanClass为User.class并注册到ApplicationContext中
AbstractBeanDefinition beanDefinition BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
beanDefinition.setScope(prototype); // 设置作用域
beanDefinition.setInitMethodName(init); // 设置初始化方法
beanDefinition.setLazyInit(true); // 设置懒加载context.registerBeanDefinition(user, beanDefinition);
System.out.println(context.getBean(user));
BeanDefinitionReader
BeanDefinition读取器虽然开发中用的很少但是源码中用得很多
AnnotatedBeanDefinitionReader
把某个类转换为BeanDefinition并且解析类上的注解
AnnotationConfigApplicationContext context new
AnnotationConfigApplicationContext(AppConfig.class);
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader new AnnotatedBeanDefinitionReader(context);
// 将User.class解析为BeanDefinition
annotatedBeanDefinitionReader.register(User.class);
System.out.println(context.getBean(user));
可以解析的注解Conditional、Scope、Lazy、Primary、DependsOn、 Role、Description
XmlBeanDefinitionReader
解析bean/标签
AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);
XmlBeanDefinitionReader xmlBeanDefinitionReader new XmlBeanDefinitionReader(context);
int i xmlBeanDefinitionReader.loadBeanDefinitions(spring.xml);
System.out.println(context.getBean(user));
ClassPathBeanDefinitionScanner
扫描器可以进行扫描扫描某个包路径对扫描到的类进行解析
AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext();
context.refresh();
ClassPathBeanDefinitionScanner scanner new ClassPathBeanDefinitionScanner(context);
scanner.scan(com.gax);
System.out.println(context.getBean(userService));
BeanFactory
Bean工厂负责创建Bean并且提供获取Bean的 API
ApplicationContext就是BeanFactory的一种
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory,
HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
...
}HierarchicalBeanFactory: 支持父子Bean工厂子Bean工厂获取不到时可以到父Bean工厂去获取
ListableBeanFactory: 展示Bean的名字、展示Bean的数量、统计的信息、拿某一个类型的Bean类似列表的功能
EnvironmentCapable: 获取环境变量的功能
ApplicationEventPublisher: 事件发布的功能
MessageSource: 国际化的功能
ResourcePatternResolver: 获取某些资源、解析某些资源的功能
Spring源码中BeanFactory接口非常重要的实现类 DefaultListableBeanFactory
ApplicationContext.getBean() 调用的就是 DefaultListableBeanFactory 的getBean()方法
DefaultListableBeanFactory 可以单独使用
DefaultListableBeanFactory beanFactory new DefaultListableBeanFactory();
AbstractBeanDefinition beanDefinition BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
beanFactory.registerBeanDefinition(user, beanDefinition);
System.out.println(beanFactory.getBean(user));
ApplicationContext
ApplicationContext是个接口实际上也是一个BeanFactory不过比BeanFactory 更加强大
1、HierarchicalBeanFactory拥有获取父BeanFactory的功能
2、ListableBeanFactory拥有获取beanNames的功能
3、ResourcePatternResolver资源加载器可以一次性获取多个资源文件资源等等
4、EnvironmentCapable可以获取运行时环境没有设置运行时环境功能
5、ApplicationEventPublisher拥有广播事件的功能没有添加事件监听器的功能
6、MessageSource拥有国际化功能
ApplicationContext两个重要的实现类
1、AnnotationConfigApplicationContext
2、ClassPathXmlApplicationContext
国际化
定义一个MessageSource
Bean
public MessageSource messageSource() {ResourceBundleMessageSource messageSource new ResourceBundleMessageSource();messageSource.setBasename(messages);return messageSource;
}
ApplicationContext拥有国际化的功能可以直接用
context.getMessage(test, null, new Locale(en_CN))
资源加载
可以利用ApplicationContext获取某个文件的内容
AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);Resource resource context.getResource(file://D:\\UserService.java);
System.out.println(resource.contentLength());
System.out.println(resource.getFilename());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/gax/*.class);
for (Resource resource : resources) {System.out.println(resource.contentLength());System.out.println(resource.getFilename());
}
获取运行时环境
AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);MapString, Object systemEnvironment context.getEnvironment().getSystemEnvironment();
System.out.println(systemEnvironment); //操作系统层面的环境变量MapString, Object systemProperties context.getEnvironment().getSystemProperties();
System.out.println(systemProperties); //运行java通过-D指定的环境变量MutablePropertySources propertySources context.getEnvironment().getPropertySources();
System.out.println(propertySources); //最强大的包含上面两种和PropertySources注解的变量System.out.println(context.getEnvironment().getProperty(NO_PROXY)); //操作系统
System.out.println(context.getEnvironment().getProperty(sun.jnu.encoding)); //jvm -D指定
System.out.println(context.getEnvironment().getProperty(gax)); //property里面的
事件发布
定义一个事件监听器
Bean
public ApplicationListener applicationListener() {return new ApplicationListener() {Overridepublic void onApplicationEvent(ApplicationEvent event) {System.out.println(接收到了一个事件);}};
}
发布一个事件
context.publishEvent(yeah); 类型转化
Spring提供了一些方便类型转化的技术
PropertyEditor
JDK中提供的类型转化工具类使用示例
public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor
{Overridepublic void setAsText(String text) throws IllegalArgumentException{User user new User();user.setName(text);this.setValue(user);}// 单独使用示例public static void main(String[] args){StringToUserPropertyEditor propertyEditor new StringToUserPropertyEditor();propertyEditor.setAsText(11);User value (User)propertyEditor.getValue();System.out.println(value);System.out.println(value.getName());}
}输出
com.gax.service.User5a07e868
11
向Spring中注册PropertyEditor
Bean
public CustomEditorConfigurer customEditorConfigurer()
{CustomEditorConfigurer customEditorConfigurer new CustomEditorConfigurer();MapClass?, Class? extends PropertyEditor propertyEditorMap new HashMap();// StringToUserPropertyEditor可以将String转化成User类型// 在Spring源码中如果当前对象是String而需要的类型是User就会用该PropertyEditor做类型转化propertyEditorMap.put(User.class, StringToUserPropertyEditor.class);customEditorConfigurer.setCustomEditors(propertyEditorMap);return customEditorConfigurer;
}// 示例代码
Component
public class UserService
{Value(ccc)private User user; //这里需要类型转换public void test(){System.out.println(user);}
}// 测试
public class Test
{public static void main(String[] args) {// 创建一个Spring容器AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(AppConfig.class);UserService userService (UserService) applicationContext.getBean(userService);userService.test();}
}输出输出的是一个User转换成功
com.gax.service.User17ed40e0 ConversionService
Spring中提供的类型转化服务它比PropertyEditor更强大
public class StringToUserConverter implements ConditionalGenericConverter
{Overridepublic boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType){return sourceType.getType().equals(String.class) targetType.getType().equals(User.class);}Overridepublic SetGenericConverter.ConvertiblePair getConvertibleTypes(){return Collections.singleton(new GenericConverter.ConvertiblePair(String.class, User.class));}Overridepublic Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType){User user new User();user.setName((String)source);return user;}
}// 单独使用
public class Test
{public static void main(String[] args) {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;
} TypeConverter
Spring提供更高级的转换类SimpleTypeConverter可以支持上面两种
public class Test
{public static void main(String[] args) {SimpleTypeConverter typeConverter new SimpleTypeConverter();typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
// DefaultConversionService conversionService new DefaultConversionService();
// conversionService.addConverter(new StringToUserConverter());
// typeConverter.setConversionService(conversionService);User value typeConverter.convertIfNecessary(1, User.class);System.out.println(value);}
}
扩展
// getBean指定类型转换
AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService applicationContext.getBean(userService, UserService.class);// 可以对应到Spring源码AbstractBeanFactory#adaptBeanInstance
T T adaptBeanInstance(String name, Object bean, Nullable Class? requiredType) {// Check if required type matches the type of the actual bean instance.if (requiredType ! null !requiredType.isInstance(bean)) {try {// SimpleTypeConverterObject convertedBean getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean null) { // 已经转换过了返回没转换报错throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return (T) convertedBean;}catch (TypeMismatchException ex) {if (logger.isTraceEnabled()) {logger.trace(Failed to convert bean name to required type ClassUtils.getQualifiedName(requiredType) , ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;
} OrderComparator
Spring所提供的一种比较器有Order注解、实现Ordered接口两种使用方式通过指定的值进行比较或排序。
实现Ordered接口示例代码
public class A implements Ordered
{Overridepublic int getOrder(){return 3;}Overridepublic String toString(){return this.getClass().getSimpleName();}
}public class B implements Ordered
{Overridepublic int getOrder(){return 2;}Overridepublic String toString(){return this.getClass().getSimpleName();}
}public class Main
{public static void main(String[] args){A a new A(); // order3B b new B(); // order2OrderComparator comparator new OrderComparator();System.out.println(comparator.compare(a, b)); // 1 (ab,ab时返回-1)List list new ArrayList();list.add(a);list.add(b);// 按order值升序排序list.sort(comparator);System.out.println(list); // BA}
}输出
1
[B, A]
Spring还提供了一个OrderComparator的子类 AnnotationAwareOrderComparator它支持用Order来指定order值
Order(3)
public class A
{Overridepublic String toString(){return this.getClass().getSimpleName();}
}Order(2)
public class B
{Overridepublic String toString(){return this.getClass().getSimpleName();}
}public class Main
{public static void main(String[] args){A a new A(); // order3B b new B(); // order2AnnotationAwareOrderComparator comparator new AnnotationAwareOrderComparator();System.out.println(comparator.compare(a, b)); // 1List list new ArrayList();list.add(a);list.add(b);// 按order值升序排序list.sort(comparator);System.out.println(list); // BA}
}输出
1
[B, A]// 关键源码AnnotationAwareOrderComparator#findOrder
protected Integer findOrder(Object obj) {// 先获取Ordered接口中getOrder()方法返回的数值Integer order super.findOrder(obj);if (order ! null) {return order;}// 如果没有实现Ordered接口则获取Order注解中指定的值return findOrderFromAnnotation(obj);
} BeanPostProcessor
BeanPostProcess表示Bean的后置处理器可以定义一个或多个BeanPostProcessor
Component
public class GaxBeanPostProcessor implements BeanPostProcessor
{Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {if (userService.equals(beanName)) {System.out.println(初始化前);}return bean;}Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if (userService.equals(beanName)) {System.out.println(初始化后);}return bean;}
}
BeanPostProcessor可以在任意一个Bean的初始化之前以及初始化之后去额外的做一些用户自定义的逻辑当然还可以通过判断beanName来进行针对性处理针对某个Bean或某部分Bean。
我们可以通过定义BeanPostProcessor来干涉Spring创建Bean的过程 BeanFactoryPostProcessor
Bean工厂的后置处理器和BeanPostProcessor类似。
BeanPostProcessor是干涉Bean的创建过程BeanFactoryPostProcessor是干涉BeanFactory的创建过程。
Component
public class GaxBeanFactoryPostProcessor implements BeanFactoryPostProcessor
{Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){System.out.println(加工beanFactory);}
} FactoryBean
上面提到可以通过BeanPostPorcessor来干涉Spring创建Bean的过程。但是如果我们想一个Bean完完全全由我们来创造也是可以的比如通过FactoryBean
Component
public class GaxFactoryBean implements FactoryBean
{Overridepublic Object getObject(){return new UserService();}Overridepublic Class? getObjectType(){return UserService.class;}
}// 测试
public class Test
{public static void main(String[] args) throws IOException{// 创建一个Spring容器AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(AppConfig.class);Object gaxFactoryBean applicationContext.getBean(gaxFactoryBean);Object gaxFactoryBean2 applicationContext.getBean(gaxFactoryBean);Object gaxFactoryBean3 applicationContext.getBean(gaxFactoryBean);System.out.println(gaxFactoryBean);System.out.println(gaxFactoryBean2);System.out.println(gaxFactoryBean3);}
}输出
com.gax.service.UserService6e3c1e69
com.gax.GaxFactoryBean5f150435
com.gax.GaxFactoryBean5f150435
注意通过这种方式创造出来的UserService的Bean只会经过初始化后其他Spring的生命周期步骤是不会经过的比如依赖注入。
通过Bean也可以生成一个对象作为Bean那么和FactoryBean的区别是什么呢
其实在很多场景下他俩是可以替换的但是站在原理层面来说的区别很明显Bean定义的Bean是会经过完整的Bean生命周期的。 ExcludeFilter和IncludeFilter
ExcludeFilter表示排除过滤器IncludeFilter表示包含过滤器
// 扫描com.gax这个包下面的所有类但是排除UserService类
// 也就是就算类上面有Component注解也不会成为Bean
ComponentScan(value com.gax, excludeFilters {ComponentScan.Filter(type FilterType.ASSIGNABLE_TYPE, classes UserService.class)})
public class AppConfig {
}// 就算UserService类上没有Component注解也会被扫描成为一个Bean
ComponentScan(value com.gax, 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内部怎么支持Component注解扫描的
在Spring的扫描逻辑中默认会添加一个AnnotationTypeFilter给includeFilters表示默认情况下 Spring扫描过程中会认为类上有Component注解的就是Bean。
// ClassPathScanningCandidateComponentProvider#registerDefaultFilters
protected void registerDefaultFilters() {// 注册Component对应的AnnotationTypeFilterthis.includeFilters.add(new AnnotationTypeFilter(Component.class));... ...
} MetadataReader、ClassMetadata、 AnnotationMetadata
在Spring中需要去解析类的信息比如类名、类中的方法、类上的注解这些都可以称之为类的元数 据所以Spring中对类的元数据做了抽象并提供了一些工具类。
public interface MetadataReader {/*** Return the resource reference for the class file.*/Resource getResource();/*** Read basic class metadata for the underlying class.*/ClassMetadata getClassMetadata();/*** Read full annotation metadata for the underlying class,* including metadata for annotated methods.*/AnnotationMetadata getAnnotationMetadata();
}// 类的元数据
public interface ClassMetadata {/*** Return the name of the underlying class.*/String getClassName();/*** Return whether the underlying class represents an interface.*/boolean isInterface();/*** Return whether the underlying class represents an annotation.* since 4.1*/boolean isAnnotation();/*** Return whether the underlying class is marked as abstract.*/boolean isAbstract();/*** Return whether the underlying class represents a concrete class,* i.e. neither an interface nor an abstract class.*/default boolean isConcrete() {return !(isInterface() || isAbstract());}... ...
}// 注解元数据
public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {/*** Get the fully qualified class names of all annotation types that* are empresent/em on the underlying class.* return the annotation type names*/default SetString getAnnotationTypes() {return getAnnotations().stream().filter(MergedAnnotation::isDirectlyPresent).map(annotation - annotation.getType().getName()).collect(Collectors.toCollection(LinkedHashSet::new));}/*** Determine whether an annotation of the given type is empresent/em on* the underlying class.* param annotationName the fully qualified class name of the annotation* type to look for* return {code true} if a matching annotation is present*/default boolean hasAnnotation(String annotationName) {return getAnnotations().isDirectlyPresent(annotationName);}/*** 可以判断类下面有没有指定注解比如说判断一个类下面有没有Bean修饰的方法* Determine whether the underlying class has an annotation that is itself* annotated with the meta-annotation of the given type.* param metaAnnotationName the fully qualified class name of the* meta-annotation type to look for* return {code true} if a matching meta-annotation is present*/default boolean hasMetaAnnotation(String metaAnnotationName) {return getAnnotations().get(metaAnnotationName,MergedAnnotation::isMetaPresent).isPresent();}... ...
}
MetadataReader表示类的元数据读取器默认实现类为SimpleMetadataReader。
public class Test
{public static void main(String[] args) throws IOException{SimpleMetadataReaderFactory simpleMetadataReaderFactory new SimpleMetadataReaderFactory();// 构造一个MetadataReaderMetadataReader metadataReader simpleMetadataReaderFactory.getMetadataReader(com.gax.service.UserService);// 得到一个ClassMetadata并获取了类名ClassMetadata classMetadata metadataReader.getClassMetadata();System.out.println(classMetadata.getClassName());// 获取一个AnnotationMetadata并获取类上的注解信息AnnotationMetadata annotationMetadata metadataReader.getAnnotationMetadata();for (String annotationType : annotationMetadata.getAnnotationTypes()){System.out.println(annotationType);}}
}输出
com.gax.service.UserService
org.springframework.stereotype.Component
注意SimpleMetadataReader去解析类时使用的ASM技术。
ASM简述把类当成普通文件通过字节流读出来如果符合字节码规范就根据字节码的格式获取类的信息
为什么要使用ASM技术
Spring启动的时候需要去扫描如果指定的包路径比较宽泛那么扫描的类是非常多的那如果在Spring启动时就把这些类全部加载进JVM了这样不太好所以使用了 ASM技术