Spring源码解析之BeanFactoryPostProcessor(⼀)
BeanFactoryPostProcessor
在前⾯⼏个章节,笔者有介绍过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呢?来看下⾯的⽰例:
ample.service;
import org.springframework.stereotype.Component;
@Component
public class OrderService {
}
ample.service;
import org.springframework.stereotype.Component;
@Component
public class UserService {
}
在Test1BeanFactoryPostProcessor类中,我们获取userService的BeanDefinition,并打印它的class对象,这⾥应该是UserService,然后我们再设置BeanDefinition的class为OrderService
Test1BeanFactoryPostProcessor.java
ample.service;
import org.springframework.beans.BeansException;
import org.springframework.fig.BeanFactoryPostProcessor;
import org.springframework.fig.ConfigurableListableBeanFactory;
import t.annotation.ScannedGenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class Test1BeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
ScannedGenericBeanDefinition beanDefinition = (ScannedGenericBeanDefinition) BeanDefinition("userService");
System.out.println("UserService beanDefinition class:" + BeanClass());
beanDefinition.setBeanClass(OrderService.class);
}
}
MyConfig.java
fig;
import t.annotation.ComponentScan;
import t.annotation.Configuration;
@Configuration
@ComponentScan("ample.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:ample.service.UserService
userService class:ample.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的实现。
那么笔者这⾥有个疑问,spring是在何时解析BeanDefinition?何时回调BeanFactoryPostProcessor?何时初始化bean?回顾测试⽤例
test01的两⾏代码,我们可以确定,前⾯的解析、回调、初始化⼀定是在test01⾥两句代码的某⼀句完成的,那么究竟是那⼀句呢?是创建应⽤上下⽂,还是打印userService对应的class对象呢?
为了定位上⾯的问题,我们对UserService和OrderService稍作修改,我们在两个类的构造函数中增加打印:
public class UserService {
public UserService() {
System.out.println("");
}
}
public class OrderService {
public OrderService() {
System.out.println("");
}
}
测试⽤例:
@Test
public void test02() {
ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
}
运⾏结果:
UserService beanDefinition class:ample.service.UserService
结果打印了两次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.scanner = new ClassPathBeanDefinitionScanner(this);
}
public void register(Class<?>... componentClasses) {
}
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
spring framework组件this();
register(componentClasses);
refresh();
}
……
}
于是我们进⼊到AbstractApplicationContext的refresh()⽅法,这个⽅法⾸先在<1>处调⽤obtainFreshBe
anFactory()获取⼀个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.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) {
}
…
…
}
之后会执⾏isterAnnotationConfigProcessors(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 (!ainsBeanDefinition(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 (!ainsBeanDefinition(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 && !ainsBeanDefinition(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 && !ainsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
ClassLoader()));
}
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 (!ainsBeanDefinition(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 (!ainsBeanDefinition(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);
return new BeanDefinitionHolder(definition, beanName);
}
…
…
}
代码<1>创建⼀个ConfigurationClassPostProcessor的BeanDefinition,这个类实现了BeanDefinitionRegistryPostProcessor接⼝,它会根据我们指定的扫描路径去扫描组件。
代码<3>创建⼀个AutowiredAnnotationBeanPostProcessor的BeanDefinition,这个类主要是⽤于注⼊标记了@Autowired和@Inject的属性。
代码<5>创建⼀个ConfigurationClassPostProcessor的BeanDefinition,这个类主要是⽤于注⼊标记了@Resource的属性。
在代码的<2>、<4>、<6>会调⽤registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String
beanName)将beanName和BeanDefinition注册到BeanDefinitionRegistry。
代码<7>处接收到registry、beanName、BeanDefinition会调⽤registry的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)⽅法,对beanName和BeanDefinition进⾏映射。
上⾯的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 {
isterBeanDefinition(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. */
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论