BeanFactoryPostProcessorjava
在前面几个章节,笔者有介绍过BeanFactoryPostProcessor接口,在spring在解析BeanDefinition以后,根据BeanDefinition初始化bean以前,会回调咱们编写的BeanFactoryPostProcessor实现类并调用postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法,spring会经过这个方法传入一个ConfigurableListableBeanFactory对象,咱们能够对这个bean工厂对象新增或修改BeanDefinition。spring初始化bean一个典型的流程,就是根据咱们标记在类上的@Component生成一个BeanDefinition,BeanDefinition中包含这个类的class对象,而后根据class对象生成实例。若是咱们编写两个Service:UserService和OrderService,并在类上标注@Component,再编写一个BeanFactoryPostProcessor接口,在接口中咱们拿到UserService的BeanDefinition,并修改class为OrderService,那么咱们从spring容器中获取userService这个bean,它的类型是UserService呢仍是OrderService呢?来看下面的示例:spring
package org.example.service; import org.springframework.stereotype.Component; @Component public class OrderService { } package org.example.service; import org.springframework.stereotype.Component; @Component public class UserService { }
在Test1BeanFactoryPostProcessor类中,咱们获取userService的BeanDefinition,并打印它的class对象,这里应该是UserService,而后咱们再设置BeanDefinition的class为OrderService安全
Test1BeanFactoryPostProcessor.javabash
package org.example.service; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.ScannedGenericBeanDefinition; import org.springframework.stereotype.Component; @Component public class Test1BeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { ScannedGenericBeanDefinition beanDefinition = (ScannedGenericBeanDefinition) beanFactory.getBeanDefinition("userService"); System.out.println("UserService beanDefinition class:" + beanDefinition.getBeanClass()); beanDefinition.setBeanClass(OrderService.class); } }
MyConfig.java多线程
package org.example.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("org.example.service") public class MyConfig { }
测试用例:并发
@Test public void test01() { ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class); System.out.println("userService class:" + ac.getBean("userService").getClass()); }
运行结果:框架
UserService beanDefinition class:class org.example.service.UserService userService class:class org.example.service.OrderService
能够看到,spring容器会回调咱们编写的bean工厂后置处理器BeanFactoryPostProcessor实现类Test1BeanFactoryPostProcessor ,在回调方法中,咱们能够从bean工厂获取spring容器已经解析的UserService对应的BeanDefinition对象,打印这个BeanDefinition对象的class对象也确实是UserService的class对象,以后咱们修改UserService对应的BeanDefinition的class对象为OrderService的class对象,以后咱们从spring容器获取beanName为userService的bean能够看到bean的实现类已经被替换成OrderService对象。这也验证笔者以前所说的一个事实,BeanFactoryPostProcessor的回调时机,是在spring容器将类解析为BeanDefinition以后,及根据BeanDefinition生成bean以前。固然,这段代码在实际开发中意义并不大,这里只是为了揭露spring的实现。ide
那么笔者这里有个疑问,spring是在什么时候解析BeanDefinition?什么时候回调BeanFactoryPostProcessor?什么时候初始化bean?回顾测试用例test01的两行代码,咱们能够肯定,前面的解析、回调、初始化必定是在test01里两句代码的某一句完成的,那么到底是那一句呢?是建立应用上下文,仍是打印userService对应的class对象呢?函数
为了定位上面的问题,咱们对UserService和OrderService稍做修改,咱们在两个类的构造函数中增长打印:post
public class UserService { public UserService() { System.out.println("UserService init..."); } } public class OrderService { public OrderService() { System.out.println("OrderService init..."); } }
测试用例:
@Test public void test02() { ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class); }
运行结果:
UserService beanDefinition class:class org.example.service.UserService OrderService init... OrderService init...
结果打印了两次OrderService构造函数的内容,一次spring根据OrderService对应的BeanDefinition进行初始化,一次是咱们修改userService对应的BeanDefinition的class为OrderService,spring根据class进行初始化。而test02只有一行初始化应用上下文的代码,至此咱们能够肯定,spring的解析BeanDefinition、回调BeanFactoryPostProcessor、初始化bean都在初始化应用上下文完成。固然,spring的应用上下文实现,有:AnnotationConfigApplication、ContextClassPathXmlApplicationContext……等等,但大部分的应用上下文实现都是在初始化的时候完成解析BeanDefinition、回调BeanFactoryPostProcessor、初始化bean这三步。
咱们在调用应用上下文的构造函数AnnotationConfigApplicationContext(Class<?>... componentClasses)时,这个函数内部会先调用默认的无参构造方法,初始化reader和scanner两个对象。调用完默认构造方法后,接着调用register(Class<?>... componentClasses)将咱们的配置类注册进reader,这一步就会根据配置类生成BeanDefinition并注册进spring容器,以后调用继承自父类AbstractApplicationContext的refresh()方法。
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { private final AnnotatedBeanDefinitionReader reader; private final ClassPathBeanDefinitionScanner scanner; public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } public void register(Class<?>... componentClasses) { Assert.notEmpty(componentClasses, "At least one component class must be specified"); this.reader.register(componentClasses); } public AnnotationConfigApplicationContext(Class<?>... componentClasses) { this(); register(componentClasses); refresh(); } …… }
因而咱们进入到AbstractApplicationContext的refresh()方法,这个方法首先在<1>处调用obtainFreshBeanFactory()获取一个beanFactory对象,在<2>、<3>会把beanFactory做为参数传入其余方法,<2>处咱们单看方法名invokeBeanFactoryPostProcessors能够知道这里是调用BeanFactoryPostProcessor接口,咱们以前编写的BeanFactoryPostProcessor实现类,就是在<2>处进行回调。<3>处单看方法名不太好理解,但若是看注释就能够知道,初始化“剩余且非懒加载”的单例对象,换言之:咱们的dao、service、controller都是在这一层完成bean的初始化以及属性注入。这里的“剩余”颇有意思,当咱们基于spring框架进行开发,大部分的bean都是单例对象,包括咱们以前的配置类(MyConfig)、BeanFactoryPostProcessor在spring容器中都会有对应的BeanDefinition和bean,咱们知道要调用一个类的方法,首先要有那个类的对象,在<2>处的invokeBeanFactoryPostProcessors能够回调咱们编写的BeanFactoryPostProcessor实现类,说明在<2>处就已经进行一部分bean的初始化了,这部分bean就包含了BeanFactoryPostProcessor的实现类。
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { …… public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { …… // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//<1> …… try { …… // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory);//<2> …… // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory);//<3> …… } catch (BeansException ex) { …… } finally { …… } } } …… }
咱们总结一下,当咱们调用AnnotationConfigApplicationContext(Class<?>... componentClasses)构造函数时,会先初始化reader和scanner两个对象,而后将配置类注册到reader后,再调用refresh()进行BeanDefinition的解析、单例bean的实例化。
如今,咱们来逐行分析AnnotationConfigApplicationContext(Class<?>... componentClasses)这个构造函数,首先这个构造函数会调用默认构造函数,进行reader和scanner的初始化,AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner接受一个BeanDefinitionRegistry接口类型的参数,而AnnotationConfigApplicationContext自己则实现了BeanDefinitionRegistry接口。
public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
从接口名BeanDefinitionRegistry自己咱们能够知道,这个接口是用来注册BeanDefinition,而接口所要求的实现,从上至下容许咱们建议beanName和BeanDefinition的映射关系、根据beanName移除BeanDefinition,根据beanName获取BeanDefinition、获取全部BeanDefinition对应的beanName,获取BeanDefinition的数量,判断beanName是否已被使用。BeanDefinition之于beanName就如bean之于beanName同样,一个BeanDefinition至少有一个beanName,同理一个bean至少有一个beanName,由于BeanDefinition和bean均可以有别名。
public interface BeanDefinitionRegistry extends AliasRegistry { void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException; void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; boolean containsBeanDefinition(String beanName); String[] getBeanDefinitionNames(); int getBeanDefinitionCount(); boolean isBeanNameInUse(String beanName); }
AnnotatedBeanDefinitionReader之因此要传入一个BeanDefinitionRegistry进行初始化,是由于在初始化AnnotatedBeanDefinitionReader对象时会把一些基础BeanDefinition注册到BeanDefinitionRegistry,由于AnnotationConfigApplicationContext这个类自己就实现了BeanDefinitionRegistry接口,因此AnnotatedBeanDefinitionReader会把BeanDefinition注册到AnnotationConfigApplicationContext,spring容器能够根据这些基础的BeanDefinition初始化一些基础组件,这些组件在spring容器一样做为bean对象而存在,这些基础组件有的能够根据咱们给定的类路径将咱们的类解析为BeanDefinition,有的能够根据@Autowired、@Inject、@Resource注解注入一个bean所依赖的bean。
当把一个BeanDefinitionRegistry对象传给AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)构造函数建立reader对象时,在下面代码<1>处对象会用字段registry指向传入的BeanDefinitionRegistry对象,方便后续向BeanDefinitionRegistry对象注册BeanDefinition。
public class AnnotatedBeanDefinitionReader { …… public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { this(registry, getOrCreateEnvironment(registry)); } public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); this.registry = registry;//<1> this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } …… }
以后会执行AnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source)方法,这个方法就是先前说的会注册多个基础BeanDefinition到BeanDefinitionRegistry,能够看到这里会调用registerPostProcessor方法在BeanDefinitionRegistry创建beanName和BeanDefinition的映射。
public abstract class AnnotationConfigUtils { …… public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); …… Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);//<1> def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));//<2> } if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);//<3> def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));//<4> } // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);//<5> def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));//<6> } // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } return beanDefs; } private static BeanDefinitionHolder registerPostProcessor( BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) { definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(beanName, definition);//<7> return new BeanDefinitionHolder(definition, beanName); } …… }
上面的registry是咱们以前建立的AnnotationConfigApplicationContext对象,若是咱们查看AnnotationConfigApplicationContext的registerBeanDefinition方法,会发现这个方法是继承父类GenericApplicationContext,而GenericApplicationContext又是使用代理模式,将registerBeanDefinition方法的工做交由一样实现了BeanDefinitionRegistry接口的DefaultListableBeanFactory类来完成。
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { private final DefaultListableBeanFactory beanFactory; …… public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); } …… @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { this.beanFactory.registerBeanDefinition(beanName, beanDefinition); } …… }
下面,咱们再来看看DefaultListableBeanFactory的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { /** Whether to allow re-registration of a different definition with the same name. */ private boolean allowBeanDefinitionOverriding = true; /** Map of bean definition objects, keyed by bean name. */ private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); /** List of bean definition names, in registration order. */ private volatile List<String> beanDefinitionNames = new ArrayList<>(256); /** Map from bean name to merged RootBeanDefinition. */ private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256); /** Names of beans that have already been created at least once. */ private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); …… public boolean isAllowBeanDefinitionOverriding() { return this.allowBeanDefinitionOverriding; } @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null");//<1> …… BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); if (existingDefinition != null) {//<2> if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } …… this.beanDefinitionMap.put(beanName, beanDefinition);//<3> } else {//<4> if (hasBeanCreationStarted()) {//<5> // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); } } else {//<6> // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } …… } protected boolean hasBeanCreationStarted() { return !this.alreadyCreated.isEmpty(); } protected void markBeanAsCreated(String beanName) {//<7> if (!this.alreadyCreated.contains(beanName)) { synchronized (this.mergedBeanDefinitions) { if (!this.alreadyCreated.contains(beanName)) { // Let the bean definition get re-merged now that we're actually creating // the bean... just in case some of its metadata changed in the meantime. clearMergedBeanDefinition(beanName); this.alreadyCreated.add(beanName); } } } } …… }
如今,咱们来总结下,在咱们用AnnotationConfigApplicationContext(Class<?>... componentClasses)建立ApplicationContext对象时,AnnotationConfigApplicationContext会先调用默认无参构造方法,在无参构造方法中进行AnnotatedBeanDefinitionReader的初始化,AnnotatedBeanDefinitionReader的构造参数须要传入一个BeanDefinitionRegistry的实现,BeanDefinitionRegistry是用来注册一些基础的beanDefinition,而AnnotationConfigApplicationContext类实现了BeanDefinitionRegistry接口,将自身对象做为参数传入到AnnotatedBeanDefinitionReader的构造函数初始化reader对象。在建立AnnotatedBeanDefinitionReader对象的时候,会把ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor这些类构形成RootBeanDefinition并注册到BeanDefinitionRegistry。
然而,AnnotationConfigApplicationContext也并非在自身完成beanName和BeanDefinition的映射关系,而是其父类GenericApplicationContext使用了代理模式在内部生成一个DefaultListableBeanFactory类型的引用,借助DefaultListableBeanFactory来完成beanName和BeanDefinition的映射创建。DefaultListableBeanFactory在注册beanName和BeanDefinition的时候,会先判断beanName和BeanDefinition是否为空,为空就要报错,若是都不为空,再判断beanName在DefaultListableBeanFactory中是否已存在对应的BeanDefinition,若是存在再判断是否容许重载?默认是容许重载。若是已存在,且容许重载,则从新在DefaultListableBeanFactory的beanDefinitionMap创建映射,若是已存在却不容许重载,则抛出异常。
若是beanName在注册时不存在已对应的BeanDefinition,那就要分两步判断了,一种是spring容器已存在bean,另外一种是还不存在bean,首先在AnnotatedBeanDefinitionReader内部注册RootBeanDefinition的时候,走的是不存在bean的分支,也就是简单的把beanName和BeanDefinition存到beanDefinitionMap,beanName加入到beanDefinitionNames集合。
若是是spring中已存在bean的状况,为了防止多线程进行BeanDefinition的注册,spring对beanDefinitionMap加上同步锁,在同步代码块中保存beanName和BeanDefinition在beanDefinitionMap上的映射,将beanName加入到beanDefinitionNames。
GenericApplicationContext实现了BeanDefinitionRegistry接口,GenericApplicationContext类中存在一个名为beanFactory的字段,类型是DefaultListableBeanFactory,在调用GenericApplicationContext实现自BeanDefinitionRegistry的方法,会转而调用DefaultListableBeanFactory对应的方法。
public interface BeanDefinitionRegistry extends AliasRegistry { …… void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException; …… BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; …… } public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { …… } public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { private final DefaultListableBeanFactory beanFactory; …… @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { this.beanFactory.registerBeanDefinition(beanName, beanDefinition); } …… @Override public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { return this.beanFactory.getBeanDefinition(beanName); } …… }
而DefaultListableBeanFactory类自己也实现了BeanDefinitionRegistry,这就是典型的代理模式。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { …… } @Override public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { BeanDefinition bd = this.beanDefinitionMap.get(beanName); …… return bd; } }