• spring源码学习之bean的加载(三)


      接着二中的继续写,那个都超过1000行了,哈,需要重新写一个,要不太长了,我都看不下去了

    7.4 初始化bean

    doCreateBean函数中有这样一行代码:这行代码中initializeBean函数就是初始化bean的逻辑
    exposedObject = initializeBean(beanName, exposedObject, mbd);

    这个方法在org.springframework.beans.factory.support包下AbstractAutowireCapableBeanFactory类下

     1 /**
     2  * Initialize the given bean instance, applying factory callbacks
     3  * as well as init methods and bean post processors.
     4  * <p>Called from {@link #createBean} for traditionally defined beans,
     5  * and from {@link #initializeBean} for existing bean instances.
     6  * @param beanName the bean name in the factory (for debugging purposes)
     7  * @param bean the new bean instance we may need to initialize
     8  * @param mbd the bean definition that the bean was created with
     9  * (can also be {@code null}, if given an existing bean instance)
    10  * @return the initialized bean instance (potentially wrapped)
    11  * @see BeanNameAware
    12  * @see BeanClassLoaderAware
    13  * @see BeanFactoryAware
    14  * @see #applyBeanPostProcessorsBeforeInitialization
    15  * @see #invokeInitMethods
    16  * @see #applyBeanPostProcessorsAfterInitialization
    17  */
    18 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    19     if (System.getSecurityManager() != null) {
    20         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    21             invokeAwareMethods(beanName, bean);
    22             return null;
    23         }, getAccessControlContext());
    24     }
    25     else {
    26         // 对特殊的bean处理:Aware、BeanClassLoader、BeanFactoryAware
    27         invokeAwareMethods(beanName, bean);
    28     }
    29 
    30     Object wrappedBean = bean;
    31     if (mbd == null || !mbd.isSynthetic()) {
    32         // 应用后处理器
    33         wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    34     }
    35 
    36     try {
    37         // 激活用户自定义的init方法
    38         invokeInitMethods(beanName, wrappedBean, mbd);
    39     }
    40     catch (Throwable ex) {
    41         throw new BeanCreationException(
    42                 (mbd != null ? mbd.getResourceDescription() : null),
    43                 beanName, "Invocation of init method failed", ex);
    44     }
    45     if (mbd == null || !mbd.isSynthetic()) {
    46         // 后处理器应用
    47         wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    48     }
    49 
    50     return wrappedBean;
    51 }

    虽说此函数的目的主要是进行客户设定的初始化方法的调用,但是除此之外还有其他必要的工作

    (1)激活Aware方法
    理解一下Aware的使用,spring中提供了一些Aware接口,比如好多org.springframework.beans.factory,这个包下好多啊,实现这些Aware接口的bean被初始化之后
    可以取得一些相应的资源,例如,实现BeanFactoryAware的bean在初始化后,spring容器会注入BeanFactory的实例,来看一下Aware的使用

     1 // 定义普通的bean
     2 public class Hello{
     3     public void say(){
     4         System.out.println("hello");
     5     }
     6 }
     7 
     8 // 定义BeanFactoryAware类型的bean
     9 public class Test implements BeanFactoryAware {
    10     private BeanFactory beanFactory;
    11     
    12     // 声明bean的时候spring会自动注入BeanFactory
    13     @override
    14     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    15         this.beanFactory = beanFactory;
    16     }
    17     
    18     public void testAware(){
    19         Hello hello = (Hello) beanFactory.getBean("hello");
    20         hello.say();
    21     }
    22 }

    基本上就是这样使用的,看一下 源码:
    这个方法在org.springframework.beans.factory.support包下AbstractAutowireCapableBeanFactory类下

     1 private void invokeAwareMethods(final String beanName, final Object bean) {
     2     if (bean instanceof Aware) {
     3         if (bean instanceof BeanNameAware) {
     4             ((BeanNameAware) bean).setBeanName(beanName);
     5         }
     6         if (bean instanceof BeanClassLoaderAware) {
     7             ClassLoader bcl = getBeanClassLoader();
     8             if (bcl != null) {
     9                 ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
    10             }
    11         }
    12         if (bean instanceof BeanFactoryAware) {
    13             ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    14         }
    15     }
    16 }

    (2)处理器的应用

    BeanPostProcessor是spring开放式架构中必不可少的亮点,给用户充足的权限去更改或者扩展spring,除了BeanPostProcessor,还有很多PostProcessor,
    当然大部分都是以此为基础,继承组BeanPostProcessor,BeanPostProcessor的使用位置就是这里,在调用客户自定义初始方法前以及调用自定义初始方法后
    分别会调用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization,使用户根据自己的需求进行自己处理
    这个方法在org.springframework.beans.factory.support包下AbstractAutowireCapableBeanFactory类下

     1 @Override
     2 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
     3         throws BeansException {
     4 
     5     Object result = existingBean;
     6     for (BeanPostProcessor processor : getBeanPostProcessors()) {
     7         Object current = processor.postProcessBeforeInitialization(result, beanName);
     8         if (current == null) {
     9             return result;
    10         }
    11         result = current;
    12     }
    13     return result;
    14 }
    15 
    16 @Override
    17 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    18         throws BeansException {
    19 
    20     Object result = existingBean;
    21     for (BeanPostProcessor processor : getBeanPostProcessors()) {
    22         Object current = processor.postProcessAfterInitialization(result, beanName);
    23         if (current == null) {
    24             return result;
    25         }
    26         result = current;
    27     }
    28     return result;
    29 }

    (3)激活自定义的init方法
    客户定制的初始化方法除了我们熟知的使用init-method配置外,还要使用自定义bean实现initializeBean接口,并在afterPropertiesSet中实现自己的初始化逻辑
    init-method与afterPropertiesSet都是在初始化bean时执行,指定顺序是afterPropertiesSet先执行,init-method再执行

    在invokeInitMethods方法中实现了这部分处理逻辑

     1 /**
     2  * Give a bean a chance to react now all its properties are set,
     3  * and a chance to know about its owning bean factory (this object).
     4  * This means checking whether the bean implements InitializingBean or defines
     5  * a custom init method, and invoking the necessary callback(s) if it does.
     6  * @param beanName the bean name in the factory (for debugging purposes)
     7  * @param bean the new bean instance we may need to initialize
     8  * @param mbd the merged bean definition that the bean was created with
     9  * (can also be {@code null}, if given an existing bean instance)
    10  * @throws Throwable if thrown by init methods or by the invocation process
    11  * @see #invokeCustomInitMethod
    12  */
    13 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
    14         throws Throwable {
    15 
    16     // 首先检查是否是InitializingBean,如果是的话就调用afterPropertiesSet()
    17     boolean isInitializingBean = (bean instanceof InitializingBean);
    18     if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    19         if (logger.isDebugEnabled()) {
    20             logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
    21         }
    22         if (System.getSecurityManager() != null) {
    23             try {
    24                 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
    25                     ((InitializingBean) bean).afterPropertiesSet();
    26                     return null;
    27                 }, getAccessControlContext());
    28             }
    29             catch (PrivilegedActionException pae) {
    30                 throw pae.getException();
    31             }
    32         }
    33         else {
    34             ((InitializingBean) bean).afterPropertiesSet();
    35         }
    36     }
    37 
    38     if (mbd != null && bean.getClass() != NullBean.class) {
    39         String initMethodName = mbd.getInitMethodName();
    40         if (StringUtils.hasLength(initMethodName) &&
    41                 !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
    42                 !mbd.isExternallyManagedInitMethod(initMethodName)) {
    43             // 调用自定义初始化方法
    44             invokeCustomInitMethod(beanName, bean, mbd);
    45         }
    46     }
    47 }

    7.5 注册DisposableBean
    spring中不但提供了对于初始化方法的扩展入口,同样也提供了销毁的扩展入口,对于销毁方法的扩展,除了我们熟知的配置属性destroy-method方法,用户还
    可以注册后处理器DestructionAwareBeanPostProcessor来统一处理bean的销毁方法

     1 /**
     2  * Add the given bean to the list of disposable beans in this factory,
     3  * registering its DisposableBean interface and/or the given destroy method
     4  * to be called on factory shutdown (if applicable). Only applies to singletons.
     5  * @param beanName the name of the bean
     6  * @param bean the bean instance
     7  * @param mbd the bean definition for the bean
     8  * @see RootBeanDefinition#isSingleton
     9  * @see RootBeanDefinition#getDependsOn
    10  * @see #registerDisposableBean
    11  * @see #registerDependentBean
    12  */
    13 protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    14     AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    15     if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
    16         if (mbd.isSingleton()) {
    17             // Register a DisposableBean implementation that performs all destruction
    18             // work for the given bean: DestructionAwareBeanPostProcessors,
    19             // DisposableBean interface, custom destroy method.
    20             // 单例模式下注册需要销毁的bean,此方法中会处理实现DisposableBean的bean,
    21             // 并且对所有的bean使用DestructionAwareBeanPostProcessor处理DisposableBean
    22             registerDisposableBean(beanName,
    23                     new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
    24         }
    25         else {
    26             // A bean with a custom scope...
    27             // 自定义scope处理
    28             Scope scope = this.scopes.get(mbd.getScope());
    29             if (scope == null) {
    30                 throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
    31             }
    32             scope.registerDestructionCallback(beanName,
    33                     new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
    34         }
    35     }
    36 }
    37 
    38 // DisposableBeanAdapter类的构造方法
    39 public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
    40         List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
    41 
    42     Assert.notNull(bean, "Disposable bean must not be null");
    43     this.bean = bean;
    44     this.beanName = beanName;
    45     this.invokeDisposableBean =
    46             (this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
    47     this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
    48     this.acc = acc;
    49     String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
    50     if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
    51             !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
    52         this.destroyMethodName = destroyMethodName;
    53         this.destroyMethod = determineDestroyMethod(destroyMethodName);
    54         if (this.destroyMethod == null) {
    55             if (beanDefinition.isEnforceDestroyMethod()) {
    56                 throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
    57                         destroyMethodName + "' on bean with name '" + beanName + "'");
    58             }
    59         }
    60         else {
    61             Class<?>[] paramTypes = this.destroyMethod.getParameterTypes();
    62             if (paramTypes.length > 1) {
    63                 throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
    64                         beanName + "' has more than one parameter - not supported as destroy method");
    65             }
    66             else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
    67                 throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
    68                         beanName + "' has a non-boolean parameter - not supported as destroy method");
    69             }
    70         }
    71     }
    72     this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
    73 }
    74 
    75 /**
    76  * Search for all DestructionAwareBeanPostProcessors in the List.
    77  * @param processors the List to search
    78  * @return the filtered List of DestructionAwareBeanPostProcessors
    79  */
    80 @Nullable
    81 private List<DestructionAwareBeanPostProcessor> filterPostProcessors(List<BeanPostProcessor> processors, Object bean) {
    82     List<DestructionAwareBeanPostProcessor> filteredPostProcessors = null;
    83     if (!CollectionUtils.isEmpty(processors)) {
    84         filteredPostProcessors = new ArrayList<>(processors.size());
    85         for (BeanPostProcessor processor : processors) {
    86             if (processor instanceof DestructionAwareBeanPostProcessor) {
    87                 DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
    88                 if (dabpp.requiresDestruction(bean)) {
    89                     filteredPostProcessors.add(dabpp);
    90                 }
    91             }
    92         }
    93     }
    94     return filteredPostProcessors;
    95 }
  • 相关阅读:
    springboot之mybatis别名的设置
    webstorm
    万字长文把 VSCode 打造成 C++ 开发利器
    残差residual VS 误差 error
    参数与非参数的机器学习算法
    阿里云产品梳理
    aws产品整理
    Azure产品整理
    OpenStack产品摘要
    头条、美团、滴滴、阿里、腾讯、百度、华为、京东职级体系及对应薪酬
  • 原文地址:https://www.cnblogs.com/ssh-html/p/11218628.html
Copyright © 2020-2023  润新知