泰安企业建站公司,域名注册查询工具,做外国人的生意哪家网站好,最近一周热点回顾前言
前几篇已经介绍lBeanFactory的创建已经xml配置文件中自定义标签和默认标签的解析过程#xff0c;此时的BeanFactory中已经包含了xml文件中的标签属性。但BeanFactory中还有一些本身重要的属性没有填充#xff0c;所以接着方法继续往下看BeanFactory中的属性是如何填充的…前言
前几篇已经介绍lBeanFactory的创建已经xml配置文件中自定义标签和默认标签的解析过程此时的BeanFactory中已经包含了xml文件中的标签属性。但BeanFactory中还有一些本身重要的属性没有填充所以接着方法继续往下看BeanFactory中的属性是如何填充的。
refresh refresh()主流程中前几个方法已经介绍过这里不过多赘述去掉后面的无用代码我们这篇帖子主要看prepareBeanFactory方法中做了些什么。
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing./*** 前戏做容器刷新前的准备工作* 1、设置容器的启动时间* 2、设置活跃状态为true* 3、设置关闭状态为false* 4、获取Environment对象并加载当前系统的属性值到Environment对象中* 5、准备监听器和事件的集合对象默认为空的集合*/prepareRefresh();// Tell the subclass to refresh the internal bean factory.// 创建容器对象DefaultListableBeanFactory// 加载xml配置文件的属性值到当前工厂中最重要的就是BeanDefinitionConfigurableListableBeanFactory beanFactory obtainFreshBeanFactory();// Prepare the bean factory for use in this context.// beanFactory的准备工作对各种属性进行填充prepareBeanFactory(beanFactory);}}prepareBeanFactory 见名知意这个方法中也是为了BeanFactory做准备工作所以刚上来设置了BeanFacroty的类加载器。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the contexts class loader etc.// 设置beanFactory的classloader为当前context的classloaderbeanFactory.setBeanClassLoader(getClassLoader());// 设置beanfactory的表达式语言处理器beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));// 为beanFactory增加一个默认的propertyEditor这个主要是对bean的属性等设置管理的一个工具类beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// Configure the bean factory with context callbacks.// 添加beanPostProcessor,ApplicationContextAwareProcessor此类用来完成某些Aware对象的注入beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// 设置要忽略自动装配的接口这些接口的实现是由容器通过set方法进行注入的// 所以在使用autowire进行注入的时候需要将这些接口进行忽略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 interface not registered as resolvable type in a plain factory.// MessageSource registered (and found for autowiring) as a bean.// 设置几个自动装配的特殊规则,当在进行ioc初始化的如果有多个实现那么就使用指定的对象进行注入beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// Register early post-processor for detecting inner beans as ApplicationListeners.// 注册BPPbeanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.// 增加对AspectJ的支持在java中织入分为三种方式分为编译器织入类加载器织入运行期织入编译器织入是指在java编译器采用特殊的编译器将切面织入到java类中// 而类加载期织入则指通过特殊的类加载器在类字节码加载到JVM时织入切面运行期织入则是采用cglib和jdk进行切面的织入// aspectj提供了两种织入方式第一种是通过特殊编译器在编译器将aspectj语言编写的切面类织入到java类中第二种是类加载期织入就是下面的load time weaving此处后续讲if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// Register default environment beans.// 注册默认的系统环境bean到一级缓存中if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}}StandardBeanExpressionResolver
这个方法主要是创建了一个标准的Bean表达式的解析器。主要是用来对spel表达式的解析。 其中类之间的关系是Resolver处理类 包含了- spelParser的解析类 包含了 - spelConfiguration配置类。其中具体的解析过程是在SpelExpressionParser中的doParseExpression()方法完成。
/*** 默认表达式前缀** Default expression prefix: #{. */public static final String DEFAULT_EXPRESSION_PREFIX #{;/*** 默认表达式后缀** Default expression suffix: }. */public static final String DEFAULT_EXPRESSION_SUFFIX };private String expressionPrefix DEFAULT_EXPRESSION_PREFIX;private String expressionSuffix DEFAULT_EXPRESSION_SUFFIX;public StandardBeanExpressionResolver(Nullable ClassLoader beanClassLoader) {this.expressionParser new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));}public SpelParserConfiguration(Nullable SpelCompilerMode compilerMode, Nullable ClassLoader compilerClassLoader,boolean autoGrowNullReferences, boolean autoGrowCollections, int maximumAutoGrowSize) {this.compilerMode (compilerMode ! null ? compilerMode : defaultCompilerMode);this.compilerClassLoader compilerClassLoader;this.autoGrowNullReferences autoGrowNullReferences;this.autoGrowCollections autoGrowCollections;this.maximumAutoGrowSize maximumAutoGrowSize;}SpelExpressionParser 省略具体解析过程。知道使用时会调用doParseExpression方法即可。
public SpelExpressionParser(SpelParserConfiguration configuration) {Assert.notNull(configuration, SpelParserConfiguration must not be null);this.configuration configuration;}Overrideprotected SpelExpression doParseExpression(String expressionString, Nullable ParserContext context) throws ParseException {return new InternalSpelExpressionParser(this.configuration).doParseExpression(expressionString, context);}回到prepareBeanFactory主方法看下面的具体方法。
addPropertyEditorRegistrar
这个方法主要是对类属性的一个扩展比如说Customer类中引用了Address变量。Address中包含了省市区的属性但Customer中对address的值是省_市_区将值捏合成了一个这时可通过自定义的扩展对类中属性进行拆分。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the contexts class loader etc.// 设置beanFactory的classloader为当前context的classloaderbeanFactory.setBeanClassLoader(getClassLoader());// 设置beanfactory的表达式语言处理器beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));// 为beanFactory增加一个默认的propertyEditor这个主要是对bean的属性等设置管理的一个工具类beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));}先看方法的具体执行流程。
ResourceEditorRegistrar addPropertyEditorRegistrar()方法会为BeanFacroty中PropertyEditorRegistrar属性赋值在PropertyEditorRegistrar的构造器中会对类中属性进行初始化赋值并在类中包含了一个registerCustomEditors()方法。 registerCustomEditors方法会将Spring中默认的一些类注册到Editors中默认的会执行overrideDefaultEditor操作。 registerCustomEditors方法会在Spring后面的源码中进行调用这里不过多讲解。
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {public ResourceEditorRegistrar(ResourceLoader resourceLoader, PropertyResolver propertyResolver) {this.resourceLoader resourceLoader;this.propertyResolver propertyResolver;}Overridepublic void registerCustomEditors(PropertyEditorRegistry registry) {ResourceEditor baseEditor new ResourceEditor(this.resourceLoader, this.propertyResolver);doRegisterEditor(registry, Resource.class, baseEditor);//省略部分doRegisterEditor代码...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);}}
}ResourceEditor ResourceEditor类继承了PropertyEditorSupportPropertyEditorSupport实现了PropertyEditor类其中ResourceEditor类包含了一些对类属性的一些实现。包括setAsTextsetValue等一些方法。
public class ResourceEditor extends PropertyEditorSupport {public void setAsText(String text) throws java.lang.IllegalArgumentException {if (value instanceof String) {setValue(text);return;}throw new java.lang.IllegalArgumentException(text);}public void setValue(Object value) {this.value value;firePropertyChange();}
}结合ResourceEditor和ResourceEditorRegistrar两者来看的话对属性的扩展就是将具体的class类通过Editor定义好具体的逻辑后通过Spring框架的识别而后根据自己定义的逻辑来针对具体的class类的属性进行处理。
自定义类属性扩展
根据上面介绍的执行流程仿照Spring框架的写法
需要类实现PropertyEditorRegistrar类并实现自己的registerCustomEditors方法将类注册到Editors类中在自定义的Editors类中重写setAsText方法实现类中的属性自定义扩展。让自定义的Registrar类能够被Spring发现并调用。
自定义类 Customer类中包含着Address属性此时Customer对address的属性设置是“”省_市_区“”的格式到Address类中要拆分成对应的值。
public class Customer {private String name;private Address address;
}public class Address {private String province;private String city;private String town;
}实现Registrar 实现Registrar调实现registerCustomEditors注册。
public class AddressPropertyEditorRegistrar implements PropertyEditorRegistrar {Overridepublic void registerCustomEditors(PropertyEditorRegistry registry) {registry.registerCustomEditor(Address.class,new AddressPropertyEditor());}
}
//根据参数text属性实现自定义扩展
public class AddressPropertyEditor extends PropertyEditorSupport {Overridepublic void setAsText(String text) throws IllegalArgumentException {String[] s text.split(_);Address address new Address();address.setProvince(s[0]);address.setCity(s[1]);address.setTown(s[2]);this.setValue(address);}
}xml配置 这里的xml采用了两种方法配置目的是让Spring框架可以发现我们自定义的Editor并进行调用。将我们自定义的Editor填充到CustomEditorConfigurer类中的customEditors属性其实就可让Spring框架发现并调用。这里埋个小坑会在后面源码具体执行调用customEditors属性时再填。 bean idcustomer classcom.xxx.selfEditor.Customerproperty namename valuezhangsan/propertyproperty nameaddress value省_市_区/property/bean
!-- bean classorg.springframework.beans.factory.config.CustomEditorConfigurer--
!-- property namepropertyEditorRegistrars--
!-- list--
!-- bean classcom.xxx.selfEditor.AddressPropertyEditorRegistrar/bean--
!-- /list--
!-- /property--
!-- /bean--bean classorg.springframework.beans.factory.config.CustomEditorConfigurerproperty namecustomEditorsmapentry keycom.xxx.selfEditor.Addressvaluecom.xxx.selfEditor.AddressPropertyEditor/value/entry/map/property/beanignoreDependencyInterface
忽略自动装配的接口这些接口的实现是由容器通过set方法进行注入的所以在使用autowire进行注入的时候需要将这些接口进行忽略。 源码中忽略类的方法有两个代表着不同的含义具体可以看这篇帖子关于ignoreDependencyInterface的方法讲述的很细。
/*** 自动装配时忽略的类** Ignore the given dependency type for autowiring:* for example, String. Default is none.* param type the dependency type to ignore*/void ignoreDependencyType(Class? type);/*** 自动装配时忽略的接口** Ignore the given dependency interface for autowiring.* pThis will typically be used by application contexts to register* dependencies that are resolved in other ways, like BeanFactory through* BeanFactoryAware or ApplicationContext through ApplicationContextAware.* pBy default, only the BeanFactoryAware interface is ignored.* For further types to ignore, invoke this method for each type.* param ifc the dependency interface to ignore* see org.springframework.beans.factory.BeanFactoryAware* see org.springframework.context.ApplicationContextAware*/void ignoreDependencyInterface(Class? ifc);