返回介绍

5.7.4 初始化 bean

发布于 2025-04-22 22:09:11 字数 6768 浏览 0 评论 0 收藏

大家应该记得在 bean 配置时 bean 中有一个 init-method 的属性,这个属性的作用是在 bean 实例化前调用 init-method 指定的方法来根据用户业务进行相应的实例化。我们现在就已经进入这个方法了,首先看一下这个方法的执行位置,Spring 中程序已经执行过 bean 的实例化,并且进行了属性的填充,而就在这时将会调用用户设定的初始化方法。

protected Object initializeBean(final String beanName, final Object bean, RootBean

Definition mbd) {

  if (System.getSecurityManager() != null) {

   AccessController.doPrivileged(new PrivilegedAction<Object>() {

    public Object run() {

    invokeAwareMethods(beanName, bean);

     return null;

   }

   }, getAccessControlContext());

 }

  else {

  //对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware

  invokeAwareMethods(beanName, bean);

 }

  Object wrappedBean = bean;

  if (mbd == null || !mbd.isSynthetic()) {

  //应用后处理器

   wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean,

  beanName);

 }

  try {

  //激活用户自定义的 init 方法

  invokeInitMethods(beanName, wrappedBean, mbd);

 }

  catch (Throwable ex) {

   throw new BeanCreationException(

   (mbd != null ? mbd.getResourceDescription() : null),

   beanName, "Invocation of init method failed", ex);

 }

  if (mbd == null || !mbd.isSynthetic()) {

  //后处理器应用

   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean,

  beanName);

 }

  return wrappedBean;

}

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

1.激活 Aware 方法

在分析其原理之前,我们先了解一下 Aware 的使用。Spring 中提供一些 Aware 相关接口,比如 BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware 等,实现这些 Aware 接口的 bean 在被初始之后,可以取得一些相对应的资源,例如实现 BeanFactoryAware 的 bean 在初始后, Spring 容器将会注入 BeanFactory 的实例,而实现 ApplicationContextAware 的 bean,在 bean 被初始后,将会被注入 ApplicationContext 的实例等。我们首先通过示例方法来了解一下 Aware 的使用。

(1)定义普通 bean。

public class Hello {

  public void say() {

  System.out.println("hello");

 }

}

(2)定义 BeanFactoryAware 类型的 bean。

public class Test implements BeanFactoryAware {

  private BeanFactory beanFactory;

 // 声明 bean 的时候 Spring 会自动注入 BeanFactory

 @Override

  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

   this.beanFactory = beanFactory;

 }

  public void testAware() {

  //通过 hello 这个 bean id 从 beanFactory 获取实例

   Hello hello = (Hello) beanFactory.getBean("hello");

  hello.say();

 }

}

(3)使用 main 方法测试。

public static void main(String[] s) {

  ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

  Test test = (Test) ctx.getBean("test");

 test.testAware();

}

运行测试类,控制台输出:

hello

按照上面的方法我们可以获取到 Spring 中 BeanFactory,并且可以根据 BeanFactory 获取所有 bean,以及进行相关设置。当然还有其他 Aware 的使用方法都大同小异,看一下 Spring 的实现方式,相信读者便会使用了。

private void invokeAwareMethods(final String beanName, final Object bean) {

  if (bean instanceof Aware) {

   if (bean instanceof BeanNameAware) {

    ((BeanNameAware) bean).setBeanName(beanName);

  }

   if (bean instanceof BeanClassLoaderAware) {

    ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());

  }

   if (bean instanceof BeanFactoryAware) {

   Factory.this);

    ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowire CapableBean

  }

 }

}

代码简单得已经没有什么好说的了。读者可以自己尝试使用别的 Aware,都比较简单。

2.处理器的应用

BeanPostProcessor 相信大家都不陌生,这是 Spring 中开放式架构中一个必不可少的亮点,给用户充足的权限去更改或者扩展 Spring ,而除了 BeanPostProcessor 外还有很多其他的 PostProcessor,当然大部分都是以此为基础,继承自 BeanPostProcessor。BeanPostProcessor 的使用位置就是这里,在调用客户自定义初始化方法前以及调用自定义初始化方法后分别会调用 BeanPostProcessor 的 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法,使用户可以根据自己的业务需求进行响应的处理。

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String

beanName)

  throws BeansException {

  Object result = existingBean;

  for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {

   result = beanProcessor.postProcessBeforeInitialization(result, beanName);

   if (result == null) {

    return result;

  }

 }

  return result;

}

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String

beanName)

  throws BeansException {

  Object result = existingBean;

  for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {

   result = beanProcessor.postProcessAfterInitialization(result, beanName);

   if (result == null) {

    return result;

  }

 }

  return result;

}

3.激活自定义的 init 方法

客户定制的初始化方法除了我们熟知的使用配置 init-method 外,还有使自定义的 bean 实现 InitializingBean 接口,并在 afterPropertiesSet 中实现自己的初始化业务逻辑。

init-method 与 afterPropertiesSet 都是在初始化 bean 时执行,执行顺序是 afterPropertiesSet 先执行,而 init-method 后执行。

在 invokeInitMethods 方法中就实现了这两个步骤的初始化方法调用。

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

throws Throwable {

 //首先会检查是否是 InitializingBean,如果是的话需要调用 afterPropertiesSet 方法

   boolean isInitializingBean = (bean instanceof InitializingBean);

   if (isInitializingBean && (mbd == null || !mbd.isExternally ManagedInitMethod

   ("afterPropertiesSet"))) {

    if (logger.isDebugEnabled()) {

     logger.debug("Invoking afterPropertiesSet() on bean with name '" +

     beanName + "'");

   }

    if (System.getSecurityManager() != null) {

     try {

      <Object>() {

      AccessController.doPrivileged(new PrivilegedExceptionAction

       public Object run() throws Exception {

        ((InitializingBean) bean).afterPropertiesSet();

        return null;

      }

      }, getAccessControlContext());

    }

     catch (PrivilegedActionException pae) {

      throw pae.getException();

    }

    }else {

    //属性初始化后的处理

     ((InitializingBean) bean).afterPropertiesSet();

   }

  }

   if (mbd != null) {

    String initMethodName = mbd.getInitMethodName();

    if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".

   equals(initMethodName)) &&

     !mbd.isExternallyManagedInitMethod(initMethodName)) {

   //调用自定义初始化方法

    invokeCustomInitMethod(beanName, bean, mbd);

  }

 }

}

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。