我爱编程

Spring 容器相关知识

2018-04-12  本文已影响0人  LeonardoEzio

一、Spring InitializingBean

Spring 为Bean提供了两种初始化方式:

1.通过实现InitializingBean 接口后实现afterPropertiesSet方法,在其中指定初始化业务逻辑。
2.通过在配置中指定init-method实现bean的初始化方法 。

afterPropertiesSet方法与init-method调用的先后顺序

1.如果afterPropertiesSet方法和init-method同时存在,先调用afterPropertiesSet方法,后调用init-method。如果调用afterPropertiesSet方法出错,则不会调用init-method。

通过AbstractAutowireCapableBeanFactory中的invokeInitMethods方法可以看出两者的调用顺序:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
        throws Throwable {

    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                    @Override
                   //调用afterPropertiesSet方法
                    public Object run() throws Exception {
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }
    //调用init-method方法
    if (mbd != null) {
        String initMethodName = mbd.getInitMethodName();
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

2.afterPropertiesSet方法是直接调用,比通过反射调用的init-method效率要高,但是init-method消除了对Spring的依赖。

二、Spring BeanFactoryPostProcessor | BeanPostProcessor

1.BeanPostProcessor : Bean的后置处理器的postProcessorBeforeInitailization方法是在bean实例化,依赖注入之后及自定义初始化方法(例如:配置文件中bean标签添加init-method属性指定Java类中初始化方法、@PostConstruct注解指定初始化方法,Java类实现InitailztingBean接口)之前调用。

2.后置处理器的postProcessorAfterInitailization方法是在bean实例化、依赖注入及自定义初始化方法之后调用。实现对Bean的再加工,属性修改和生成代理。

3.BeanPostProcessor 与 InitializingBean和DisposableBean的区别:
BeanPostProcessor将对所有的Bean起作用,即所有的bean初始化前后都会回调BeanPostProcessor实现类,InitializingBean 和 DisposableBean 针对单个bean,即只有在对应的bean实现了InitializingBean或DisposableBean接口才会对其进行回调。

三、BeanDefinitionRegistryPostProcessor

1.通过postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) 可以让我们实现自定义的注册bean定义的逻辑。

 public class CustomBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor {

    @Override
     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
          RootBeanDefinition helloBean = new RootBeanDefinition(Hello.class);
    //新增Bean定义
          registry.registerBeanDefinition("hello", helloBean);
    }
}

2.与ClassPathScanningCandidateComponentProvider配合使用,根据一定的规则扫描类路径下满足特定条件的Class来作为候选的bean定义。

列:扫描指定包及其子包下面的所有非接口和非抽象类

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
     boolean useDefaultFilters = false;//是否使用默认的filter,使用默认的filter意味着只扫描那些类上拥有Component、Service、Repository或Controller注解的类。
     String basePackage = "com.elim.learn.spring.bean";
     ClassPathScanningCandidateComponentProvider beanScanner = new ClassPathScanningCandidateComponentProvider(useDefaultFilters);
     TypeFilter includeFilter = new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
                  return metadataReader.getClassMetadata().isConcrete();
            }   
    };
 
    beanScanner.addIncludeFilter(includeFilter);
    Set<BeanDefinition> beanDefinitions = beanScanner.findCandidateComponents(basePackage);
    for (BeanDefinition beanDefinition : beanDefinitions) {
    //beanName通常由对应的BeanNameGenerator来生成,比如Spring自带的AnnotationBeanNameGenerator、DefaultBeanNameGenerator等,也可以自己实现。
         String beanName = beanDefinition.getBeanClassName();
         registry.registerBeanDefinition(beanName, beanDefinition);
    }
 }

补充:

上一篇 下一篇

猜你喜欢

热点阅读