先看一个Spring中Bean的实例化过程:

1.配置文件中指定Bean的init-method参数

<bean class="com.jts.service.UserService" init-method="init"></bean>

缺点:注解方式实例化Bean时无法使用

2.Bean实现InitializingBean接口(推荐,Spring源码和框架搭建中大量使用)

InitializingBean接口只有一个方法afterPropertiesSet,实例化Bean时会调用该方法

注意:

1.如果两种方式同时存在,会先执行afterPropertiesSet方法后执行init-method指定的方法,原因见Spring源码AbstractAutowireCapableBeanFactory类invokeInitMethods方法

2.实现接口为直接调用afterPropertiesSet方法,配置init-method为反射调用,所有实现接口效率较高

   /**
* Give a bean a chance to react now all its properties are set,
* and a chance to know about its owning bean factory (this object).
* This means checking whether the bean implements InitializingBean or defines
* a custom init method, and invoking the necessary callback(s) if it does.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the merged bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @throws Throwable if thrown by init methods or by the invocation process
* @see #invokeCustomInitMethod
*/
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
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);
}
}
}
    /**
* Invoke the specified custom init method on the given bean.
* Called by invokeInitMethods.
* <p>Can be overridden in subclasses for custom resolution of init
* methods with arguments.
* @see #invokeInitMethods
*/
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
String initMethodName = mbd.getInitMethodName();
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
}
else {
if (logger.isDebugEnabled()) {
logger.debug("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
} if (logger.isDebugEnabled()) {
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
} if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
ReflectionUtils.makeAccessible(initMethod);
return null;
}
});
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
initMethod.invoke(bean);
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
}
else {
try {
ReflectionUtils.makeAccessible(initMethod);
initMethod.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}

Spring容器自动调用方法的两种方式的更多相关文章

  1. Spring加载properties文件的两种方式

    在项目中如果有些参数经常需要修改,或者后期可能需要修改,那我们最好把这些参数放到properties文件中,源代码中读取properties里面的配置,这样后期只需要改动properties文件即可, ...

  2. Spring Boot定义系统启动任务的两种方式

    Spring Boot定义系统启动任务的两种方式 概述 如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web ...

  3. Spring Boot 中实现定时任务的两种方式

    在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Qua ...

  4. Unity调用Android的两种方式:其一、调用jar包

    unity在Android端开发的时候,免不了要调用Java:Unity可以通过两种方式来调用Android:一是调用jar.二是调用aar. 这篇文章主要讲解怎么从无到有的生成一个jar包,然后un ...

  5. 软件调用QML的两种方式

    一.两种方式 二.方式1[对窗口的控制权在QML] 三.方式2[对窗口的控制权在C++]

  6. Spring系列之AOP实现的两种方式

    AOP常用的实现方式有两种,一种是采用声明的方式来实现(基于XML),一种是采用注解的方式来实现(基于AspectJ). 首先复习下AOP中一些比较重要的概念: Joinpoint(连接点):程序执行 ...

  7. spring的面向切面实现的两种方式

    面向切面:主要应用在日志记录方面.实现业务与日志记录分离开发. spring面向切面有两种实现方式:1.注解 2.xml配置. 1.注解实现如下: (1)配置如下: <?xml version= ...

  8. 在Spring整合aspectj实现aop的两种方式

    -----------------------------基于XML配置方案目标对象接口1 public interface IUserService { public void add(); pub ...

  9. python之子类调用父类的两种方式

    第一种方式 直接在子类中调用父类名: Vehicle.__init__(self,name,speed,load,power)#调用父类的实例 Vehicle.run(self) #调用父类的方法 # ...

随机推荐

  1. 设计模式 - 动态代理原理及模仿JDK Proxy 写一个属于自己的动态代理

    本篇文章代码内容较多,讲的可能会有些粗糙,大家可以选择性阅读. 本篇文章的目的是简单的分析动态代理的原理及模仿JDK Proxy手写一个动态代理以及对几种代理做一个总结. 对于代理模式的介绍和讲解,网 ...

  2. Spring Boot 2.x基础教程:Swagger静态文档的生成

    前言 通过之前的两篇关于Swagger入门以及具体使用细节的介绍之后,我们已经能够轻松地为Spring MVC的Web项目自动构建出API文档了.如果您还不熟悉这块,可以先阅读: Spring Boo ...

  3. smp_processor_id()获取当前执行cpu_id

    基于Linux 2.6.32内核进行分析,看本篇文章前,建议先看看percpu变量这篇文章 smp_processor_id()用来获取当前cpu的id,首先来看smp_processor_id的定义 ...

  4. Linux之常用命令II

    一.VI编辑器 1) 概述 ◆  Visual Interface(可视化接口): ◆  类似Windows中的记事本,比记事本强大: ◆  VIM相对于VI做了哪些提升 -VIM支持多级撤销 -VI ...

  5. 基于Spark的电影推荐系统(推荐系统~2)

    第四部分-推荐系统-数据ETL 本模块完成数据清洗,并将清洗后的数据load到Hive数据表里面去 前置准备: spark +hive vim $SPARK_HOME/conf/hive-site.x ...

  6. django-drf框架自带的路由以及最简化的视图

    0910自我总结 django-drf框架自带的路由以及最简化的视图 路由 一.导入模块 from rest_framework.routers import SimpleRouter 二.初始化路由 ...

  7. Web安全之CSRF漏洞整理总结

    这两天整理和编写了csrf的靶场,顺便也复习了以前学习csrf的点,这里记录下学习的总结点. 0x01 关于CSRF 跨站请求伪造 CSRF(Cross-site request forgery)跨站 ...

  8. JZOJ5771【NOIP2008模拟】遨游

    Description      MWH寒假外出旅游,来到了S国.S国划分为N个省,第i个省有Ti座城市,编号分别为Ci1,Ci2,……CiTi(各省城市编号不会重复).所有城市间有M条双向的道路连接 ...

  9. Go 零基础 30 min 入门

        不知不觉用 Go 开发也两年多了. 筹备点经验汇总, 方便后面的同学能快速上手.  提纲     1. Go 安装     2. Go ide 搭建     3. Go modules 模块管 ...

  10. 第三篇-分析日志和sensor-data中的数据结构

    分析日志和sensor-data数据结构 该文章提供web端思路,ios和android端思路不提供,api也已经下线,本文也不提供任何可执行代码.有更多疑问欢迎查看github代码 协议 授权协议: ...