protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { //设置beanFactory的ClassLoader为当前context的classloader beanFactory.setBeanClassLoader(this.getClassLoader()); //设置beanFactory的表达式语言处理器,spring3开始支持 //默认支持#{bean.xxx}来调用相关属性 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //对beanFactory增加一个默认的PropertyEditor,这个主要是对bean的属性等设置管理 //的一个工具 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment())); //增加BeanPostProcessor beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //设置忽略自动装配的接口 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); //设置自动装配的特殊规则 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); //对AspectJ的支持 if (beanFactory.containsBean("loadTimeWeaver")) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } //添加默认的系统环境 if (!beanFactory.containsLocalBean("environment")) { beanFactory.registerSingleton("environment", this.getEnvironment()); } if (!beanFactory.containsLocalBean("systemProperties")) { beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean("systemEnvironment")) { beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment()); } }
一、扩展的功能
1、对SPEL的扩展
2、对属性编辑器的支持
3、设置可以忽略的自动装配的接口
4、注册一些固定依赖的属性
5、增加对AspectJ的支持
二、SPEL的扩展
举一个简单的例子
<bean id="user" name="user2" class="com.springboot2.test.User"/> <alias name="user2" alias="user3"/> <bean id="stu" class="com.springboot2.test.Stu"> <property name="user" value="#{user}"></property> </bean>
spring通过如下方法可以注册对SPEL的解析
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
spring在bean的进行初始化的时候会有属性填充的一步,而在这一步中会调用AbstractAutowireCapableBeanFactory类中的applyPropertyValues方法完成解析的。
在applyPropertyValues通过构造BeanDefinitionValueResolver对象,调用resolveValueIfNecessary方法,在这个方法里调用evaluate
protected Object evaluate(TypedStringValue value) { Object result = doEvaluate(value.getValue()); if (!ObjectUtils.nullSafeEquals(result, value.getValue())) { value.setDynamic(); } return result; }private Object doEvaluate(@Nullable String value) { return this.beanFactory.evaluateBeanDefinitionString(value, this.beanDefinition); }protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) { if (this.beanExpressionResolver == null) { return value; } Scope scope = null; if (beanDefinition != null) { String scopeName = beanDefinition.getScope(); if (scopeName != null) { scope = getRegisteredScope(scopeName); } } //解析SPEL return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope)); }
应用语言解析器的调用主要是在解析依赖注入bean的时候,以及在完成bean的初始化和属性获取后进行属性填充的时候。
三、属性编辑器的支持
public class Stu { private Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }<bean id="stu" class="com.springboot2.test.Stu"> <property name="date" value="2021-10-26"></property> </bean>
当获取Stu的bean时,会报错,因为spring对子自定义类型转换失败而报错
spring会采用两种解决方式
1、使用自定义属性编辑器
public class DatePropertyEditor extends PropertyEditorSupport { private String format = "yyyy-MM-dd"; public void setFormat(String format) { this.format = format; } @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format); try { Date parse = simpleDateFormat.parse(text); this.setValue(parse); } catch (ParseException e) { e.printStackTrace(); } } }<bean id="stu" class="com.springboot2.test.Stu"> <property name="date" value="2021-10-26"></property> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date" value="com.springboot2.test.DatePropertyEditor"/> </map> </property> </bean>
2、注册spring自带的属性编辑器CustomDateEditor
public class DatePropertyEditorRegistrar implements PropertyEditorRegistrar { @Override public void registerCustomEditors(PropertyEditorRegistry registry) { registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),true)); } }<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="propertyEditorRegistrars"> <list> <bean class="com.springboot2.test.DatePropertyEditorRegistrar"></bean> </list> </property> </bean>
属性编辑器的源码解析
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
进入ResourceEditorRegistrar类中最核心方法为registerCustomEditors
public void registerCustomEditors(PropertyEditorRegistry registry) { ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver); doRegisterEditor(registry, Resource.class, baseEditor); doRegisterEditor(registry, ContextResource.class, baseEditor); doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor)); doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor)); doRegisterEditor(registry, File.class, new FileEditor(baseEditor)); doRegisterEditor(registry, Path.class, new PathEditor(baseEditor)); doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor)); doRegisterEditor(registry, URL.class, new URLEditor(baseEditor)); ClassLoader classLoader = this.resourceLoader.getClassLoader(); doRegisterEditor(registry, URI.class, new URIEditor(classLoader)); doRegisterEditor(registry, Class.class, new ClassEditor(classLoader)); doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader)); if (this.resourceLoader instanceof ResourcePatternResolver) { doRegisterEditor(registry, Resource[].class, new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver)); } }
private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) { if (registry instanceof PropertyEditorRegistrySupport) { ((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor); } else { //自定义属性编辑器 registry.registerCustomEditor(requiredType, editor); } }
可以看到registerCustomEditors方法核心逻辑是注册一些列常用的类型的属性编辑器
例如,
doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
注册后,一旦某个实体bean中存在一些Class类型的属性,那么spring会调用ClassEditor将配置中心定义的String类型转换为Class类型并进行赋值
注意,beanFactory.addPropertyEditorRegistrar只是注册ResourceEditorRegistrar,但是ResourceEditorRegistrar里的方法registerCustomEditors什么时候被调用?
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
经过排查,在AbstractBeanFactory的initBeanWrapper调用了registerCustomEditors
protected void initBeanWrapper(BeanWrapper bw) { bw.setConversionService(getConversionService()); registerCustomEditors(bw); }
initBeanWrapper是之前讨论过,在bean初始化时使用的方法,用于将BeanDefinition转换为BeanWrapper后对属性填充。
总结
在bean的初始化后调用ResourceEditorRegistrar的registerCustomEditors方法进行批量的通用属性编辑器注册,注册后,在属性填充的环节直接让spring使用这些编辑器对属性解析。
四、添加ApplicationContextAwareProcessor处理器
ApplicationContextAwareProcessor中最重要的方法postProcessBeforeInitialization
postProcessBeforeInitialization方法调用了invokeAwareInterfaces方法,对实现Aware接口的bean在被初始化后,可以取得一些对应的资源。
五、忽略依赖
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
使用ignoreDependencyInterface方法忽略的bean,在做bean的依赖注入的时候忽略。
六、注册依赖
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
注册了依赖后,当bean的属性注入时,一旦检测到属性为BeanFactory类型,便会将BeanFactory的实例注入进去。