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

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


类型转化

  • PropertyEditor

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

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);

向Spring中注册PropertyEditor:

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

假设现在有如下Bean:

@Component
public class UserService {

	@Value("tiantian")
	private User user;

	public void test() {
		System.out.println(user);
	}
}

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

  • ConversionService

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

public class StringToUserConverter implements ConditionalGenericConverter {

	@Override
	public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
		return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);
	}

	@Override
	public Set 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;
}
  • TypeConverter

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

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

OrderComparator

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

public class A implements Ordered {

	@Override
	public int getOrder() {
		return 3;
	}

	@Override
	public String toString() {
		return this.getClass().getSimpleName();
	}
}
public class B implements Ordered {

	@Override
	public int getOrder() {
		return 2;
	}

	@Override
	public String toString() {
		return this.getClass().getSimpleName();
	}
}
public class Main {

	public static void main(String[] args) {
		A a = new A(); // order=3
		B b = new B(); // order=2

		OrderComparator comparator = new OrderComparator();
		System.out.println(comparator.compare(a, b));  // 1

		List list = new ArrayList<>();
		list.add(a);
		list.add(b);

		// 按order值升序排序
		list.sort(comparator);

		System.out.println(list);  // B,A
	}
}

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

BeanPostProcessor

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

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

@Component
public class TestBeanPostProcessor implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("初始化前");
		}

		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("初始化后");
		}

		return bean;
	}
}

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

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

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

BeanFactoryPostProcessor

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

@Component
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("加工beanFactory");
	}
}

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

FactoryBean

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

@Component
public class TestFactoryBean implements FactoryBean {

	//获取要创建的Bean对象
	@Override
	public Object getObject() throws Exception {
		UserService userService = new UserService();
		return userService;
	}

	//获取Bean对象的类型
	@Override
	public Class<?> getObjectType() {
		return UserService.class;
	}
}

通过上面这段代码,我们自己创造了一个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",
		excludeFilters = {@ComponentScan.Filter(
            	type = FilterType.ASSIGNABLE_TYPE, 
            	classes = UserService.class)}.)
public class AppConfig {
}

@ComponentScan(value = "com.spring",
		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的扫描逻辑中,默认会添加一个AnnotationTypeFilter给includeFilters,表示默认情况下Spring扫描过程中会认为类上有@Component注解的就是Bean。

MetadataReader、ClassMetadata、AnnotationMetadata

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

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

public class Test {
        public static void main(String[] args) throws IOException {
            SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();

            // 构造一个MetadataReader
            MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.spring.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);
            }
        }
    }

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

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

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章