网络知识 娱乐 Spring Framework之核心概念及组件(二)

Spring Framework之核心概念及组件(二)

接上文Spring Framework之核心概念及组件(一),本文继续讨论SpringFramework的核心概念及组件,方便后续阅读其源码。


类型转化

  • PropertyEditor

PropertyEditor是JDK提供的类型转化工具

public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {n @Overriden public void setAsText(String text) throws IllegalArgumentException {n User user = new User();n user.setName(text);n this.setValue(user);n }n }

StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();npropertyEditor.setAsText("1");nUser value = (User) propertyEditor.getValue();nSystem.out.println(value);

向Spring中注册PropertyEditor:

@Beannpublic CustomEditorConfigurer customEditorConfigurer() {ntCustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();ntMap<Class<?>, Class<? extends PropertyEditor>> propertyEditorMap = new HashMap<>();n n t//表示StringToUserPropertyEditor可以将String转化成User类型,n t//在Spring源码中,如果发现当前对象是String,而需要的类型是User,n t//就会使用该PropertyEditor来做类型转化ntpropertyEditorMap.put(User.class, StringToUserPropertyEditor.class);ntcustomEditorConfigurer.setCustomEditors(propertyEditorMap);ntreturn customEditorConfigurer;n}

假设现在有如下Bean:

@Componentnpublic class UserService {nnt@Value("tiantian")ntprivate User user;nntpublic void test() {nttSystem.out.println(user);nt}n}

那么test属性就能正常的完成属性赋值

  • ConversionService

ConversionService是spring提供的类型转化工具,它比PropertyEditor更强大

public class StringToUserConverter implements ConditionalGenericConverter {nnt@Overridentpublic boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {nttreturn sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);nt}nnt@Overridentpublic Set<ConvertiblePair> getConvertibleTypes() {nttreturn Collections.singleton(new ConvertiblePair(String.class, User.class));nt}nnt@Overridentpublic Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {nttUser user = new User();nttuser.setName((String)source);nttreturn user;nt}n}

DefaultConversionService conversionService = new DefaultConversionService();nconversionService.addConverter(new StringToUserConverter());nUser value = conversionService.convert("1", User.class);nSystem.out.println(value);

向Spring中注册ConversionService:

@Beannpublic ConversionServiceFactoryBean conversionService() {ntConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();ntconversionServiceFactoryBean.setConverters(Collections.singleton(new StringToUserConverter()));nntreturn conversionServiceFactoryBean;n}

  • TypeConverter

由于无法确定配置的是哪种类型转换器,spring内部同时兼容了PropertyEditor和ConversionService,而需要进行类型转换时,入口就是TypeConverter。

SimpleTypeConverter typeConverter = new SimpleTypeConverter();n//PropertyEditor注册ntypeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());n//ConversionService注册n//typeConverter.setConversionService(conversionService);nUser value = typeConverter.convertIfNecessary("1", User.class);nSystem.out.println(value);

OrderComparator

OrderComparator是Spring所提供的一种比较器,可以用来根据@Order注解或实现Ordered接口来执行值进行比较,从而实现排序效果。

public class A implements Ordered {nnt@Overridentpublic int getOrder() {nttreturn 3;nt}nnt@Overridentpublic String toString() {nttreturn this.getClass().getSimpleName();nt}n}

public class B implements Ordered {nnt@Overridentpublic int getOrder() {nttreturn 2;nt}nnt@Overridentpublic String toString() {nttreturn this.getClass().getSimpleName();nt}n}

public class Main {nntpublic static void main(String[] args) {nttA a = new A(); // order=3nttB b = new B(); // order=2nnttOrderComparator comparator = new OrderComparator();nttSystem.out.println(comparator.compare(a, b)); // 1nnttList list = new ArrayList<>();nttlist.add(a);nttlist.add(b);nntt// 按order值升序排序nttlist.sort(comparator);nnttSystem.out.println(list); // B,Ant}n}

spring还提供了AnnotationAwareOrderComparator支持注解方式使用,原理都一样,这里就不重复示例了,感兴趣的同学可以使用试试,比较简单。

BeanPostProcessor

核心功能,功能非常强大,spring的依赖注入,AOP等核心功能都是依赖它对Bean的创建进行拓展处理

BeanPostProcess表示Bena的后置处理器,我们可以定义一个或多个BeanPostProcessor,比如通过一下代码定义一个BeanPostProcessor:

@Componentnpublic class TestBeanPostProcessor implements BeanPostProcessor {nnt@Overridentpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {nttif ("userService".equals(beanName)) {ntttSystem.out.println("初始化前");ntt}nnttreturn bean;nt}nnt@Overridentpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {nttif ("userService".equals(beanName)) {ntttSystem.out.println("初始化后");ntt}nnttreturn bean;nt}n}

一个BeanPostProcessor可以在任意一个Bean初始化之前以及初始化之后去额外的做一些用户自定义的逻辑,当然,我们可以通过判断beanName来进行针对性处理(针对某个Bean,或某部分Bean)。

我们可以通过定义BeanPostProcessor来干涉Spring创建Bean的过程。

相对应的,还有实例化前后的BeanPostProcessor来对实例化过程进行干扰,会在后续篇幅重点讲解。

BeanFactoryPostProcessor

BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似,BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。比如,我们可以这样定义一个BeanFactoryPostProcessor:

@Componentnpublic class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {nnt@Overridentpublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {nttSystem.out.println("加工beanFactory");nt}n}

我们可以在postProcessBeanFactory()方法中对BeanFactory进行加工。

FactoryBean

如果我们想一个Bean完完全全由我们来创造,可以通过FactoryBean:

@Componentnpublic class TestFactoryBean implements FactoryBean {nnt//获取要创建的Bean对象nt@Overridentpublic Object getObject() throws Exception {nttUserService userService = new UserService();nttreturn userService;nt}nnt//获取Bean对象的类型nt@Overridentpublic Class<?> getObjectType() {nttreturn UserService.class;nt}n}

通过上面这段代码,我们自己创造了一个UserService对象,并且它将成为Bean。但是通过这种方式创造出来的UserService的Bean,只会经过初始化后,其他Spring的生命周期步骤是不会经过的,比如依赖注入。

初始化后时Bean生命周期的一个节点,主要也是通过BeanPostProcessor后置实现。

与@Bean不同的是,FactoryBean创建的对象是不会经历完整的Bean生命周期的。

ExcludeFilter和IncludeFilter

ExcludeFilter表示排除过滤器,IncludeFilter表示包含过滤器

它们分别指定spring在扫描Bean时,需要排除的类以及需要包含的类

优先级高于@Component注解,ExcludeFilter指向的类即使包含@Component也会被排除,同理,IncludeFilter指向的类即使不包含@Component也会生成Bean

@ComponentScan(value = "com.spring",nttexcludeFilters = {@ComponentScan.Filter(n ttype = FilterType.ASSIGNABLE_TYPE, n tclasses = UserService.class)}.)npublic class AppConfig {n}nn@ComponentScan(value = "com.spring",nttincludeFilters = {@ComponentScan.Filter(n ttype = FilterType.ASSIGNABLE_TYPE, n tclasses = UserService.class)})npublic class AppConfig {n}

FilterType分为:

  1. ANNOTATION:表示是否包含某个注解
  2. ASSIGNABLE_TYPE:表示是否是某个类
  3. ASPECTJ:表示否是符合某个Aspectj表达式
  4. REGEX:表示是否符合某个正则表达式
  5. CUSTOM:自定义

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

MetadataReader、ClassMetadata、AnnotationMetadata

在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。

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

public class Test {n public static void main(String[] args) throws IOException {n SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();nn // 构造一个MetadataReadern MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.spring.service.UserService");nn // 得到一个ClassMetadata,并获取了类名n ClassMetadata classMetadata = metadataReader.getClassMetadata();nn System.out.println(classMetadata.getClassName());nn // 获取一个AnnotationMetadata,并获取类上的注解信息n AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();n for (String annotationType : annotationMetadata.getAnnotationTypes()) {n System.out.println(annotationType);n }n }n }

需要注意的是,SimpleMetadataReader去解析类时,使用的ASM技术

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