spring InitializingBean

spring InitializingBean

大家好,又见面了,我是全栈君。

先说总结:


1:spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用


2:实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是init-method方式消除了对spring的依赖


3:如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。


4:TransactionTemplate实现InitializingBean接口,主要是判断transactionManager是否已经初始化,如果没有则抛出异常。源码如下:


     public void afterPropertiesSet() {



        if (this.transactionManager == null) {



            throw new IllegalArgumentException(“Property ‘transactionManager’ is required”);


        }


    }



TransactionTemplate的源码如下:


public class TransactionTemplate extends DefaultTransactionDefinition


        implements TransactionOperations, InitializingBean{



        .


        .


        .


        }


TransactionTemplate继承了DefaultTransactionDefinition,实现了TransactionOperations,InitializingBean接口。先研究InitializingBean接口


InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法。


测试程序如下:


import org.springframework.beans.factory.InitializingBean;


public class TestInitializingBean implements InitializingBean{





    @Override


    public void afterPropertiesSet() throws Exception {



        System.out.println(“ceshi InitializingBean”);        


    }


    public void testInit(){



        System.out.println(“ceshi init-method”);        


    }


}


配置文件如下:


<?xml version=”1.0″ encoding=”UTF-8″?>


<beans xmlns=”http://www.springframework.org/schema/beans”


    xmlns:context=”http://www.springframework.org/schema/context”


    xmlns:jdbc=”http://www.springframework.org/schema/jdbc” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”


    xmlns:p=”http://www.springframework.org/schema/p” xmlns:aop=”http://www.springframework.org/schema/aop”


    xmlns:tx=”http://www.springframework.org/schema/tx”


    xsi:schemaLocation=”


    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd”>


    <bean id=”testInitializingBean” class=”com.TestInitializingBean” ></bean>


</beans>


Main主程序如下:


public class Main {



    public static void main(String[] args){



        ApplicationContext context = new FileSystemXmlApplicationContext(“/src/main/java/com/beans.xml”);


    }


}


运行Main程序,打印如下结果:


ceshi InitializingBean  


这说明在spring初始化bean的时候,如果bean实现了InitializingBean接口,会自动调用afterPropertiesSet方法。


问题:实现InitializingBean接口与在配置文件中指定init-method有什么不同?


修改配置文件,加上init-method配置,修改如下:


<?xml version=”1.0″ encoding=”UTF-8″?>


<beans xmlns=”http://www.springframework.org/schema/beans”


    xmlns:context=”http://www.springframework.org/schema/context”


    xmlns:jdbc=”http://www.springframework.org/schema/jdbc” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”


    xmlns:p=”http://www.springframework.org/schema/p” xmlns:aop=”http://www.springframework.org/schema/aop”


    xmlns:tx=”http://www.springframework.org/schema/tx”


    xsi:schemaLocation=”


    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd”>


    <bean id=”testInitializingBean” class=”com.TestInitializingBean” init-method=”testInit”></bean>


</beans>


在配置文件中加入init-method=”testInit”。


运行Main程序,打印如下结果:


ceshi InitializingBean


ceshi init-method


由 结果可看出,在spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init- method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法。




这方式在spring中是怎么实现的?


通过查看spring的加载bean的源码类(AbstractAutowireCapableBeanFactory)可看出其中奥妙


AbstractAutowireCapableBeanFactory类中的invokeInitMethods讲解的非常清楚,源码如下:


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


            throws Throwable {



//判断该bean是否实现了实现了InitializingBean接口,如果实现了InitializingBean接口,则只掉调用bean的afterPropertiesSet方法


        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>() {



                        public Object run() throws Exception {



                         
   //直接调用afterPropertiesSet


                            ((InitializingBean) bean).afterPropertiesSet();


                            return null;


                        }


                    },getAccessControlContext());


                } catch (PrivilegedActionException pae) {



                    throw pae.getException();


                }


            }                


            else {



                
//直接调用afterPropertiesSet


                ((InitializingBean) bean).afterPropertiesSet();


            }


        }


        if (mbd != null) {



            String initMethodName = mbd.getInitMethodName();


           
 //判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-method


            if (initMethodName != null && !(isInitializingBean && “afterPropertiesSet”.equals(initMethodName)) &&


                    !mbd.isExternallyManagedInitMethod(initMethodName)) {



                    
//进一步查看该方法的源码,可以发现init-method方法中指定的方法是通过反射实现


                invokeCustomInitMethod(beanName, bean, mbd);


            }


        }


    }



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/108602.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 关于sources.list和apt-get [转载]

    关于sources.list和apt-get [转载]

    2021年11月16日
  • volatile为什么不能保证原子性

    volatile为什么不能保证原子性首先要了解的是,volatile可以保证可见性和顺序性,这些都很好理解,那么它为什么不能保证原子性呢?可见性可见性与Java的内存模型有关,模型采用缓存与主存的方式对变量进行操作,也就是说,每个线程都有自己的缓存空间,对变量的操作都是在缓存中进行的,之后再将修改后的值返回到主存中,这就带来了问题,有可能一个线程在将共享变量修改后,还没有来的及将缓存中的变量返回给主存中,另外一个线程就对…

  • pdaf的一些计算「建议收藏」

    pdaf的一些计算「建议收藏」 Pdaf数据获取流程根据上层的isCommand命令,在otp中获取到pdinfo。构建flowcontrolpdaf相关信息的结构体pd_profile,通过sendCommand在snesordriver文件中获取信息pdafcapacity、pdafinfo、vcinfo、cropwininfo。将矫正数据送入PDcore中,会将otp中的pdinfo和driver中进行对比,不一致则报错。在convertPDBufFormat中将pd点统一转换成raw16的格式,

  • C# WinForm开发系列之如何使用panel控件制作左侧导航菜单

    C# WinForm开发系列之如何使用panel控件制作左侧导航菜单之前需要写一个C#的左侧导航菜单控件,想了许久,最终选择了使用paenl控件来实现这一功能。决定和大家分享一下,初步接触C#,欢迎多多指教,不胜感激!首先,我的思路分为以下几步:一.使用vs编辑工具创建一个导航菜单控件;如图1所示:图1二.在菜单控件上布局你的导航菜单控件的样式;其结构如图2所示,(我是通过5个panel控件和两个label控件组成):

  • BS架构和CS架构的优缺点

    BS架构和CS架构的优缺点1、CS、BS架构定义  CS(Client/Server):客户端—-服务器结构。C/S结构在技术上很成熟,它的主要特点是交互性强、具有安全的存取模式、网络通信量低、响应速度快、利于处理大量数据。因为客户端要负责绝大多数的业务逻辑和UI展示,又称为胖客户端。它充分利用两端硬件,将任务分配到Client和Server两端,降低了系统的通讯开销。C/S结构的软件需要针对不同的操作系

  • win7默认共享(win7开启默认共享)

    访问win7默认共享:HEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\SystemDWORD值LocalAccountTokenFilterPolicy设置16数据值数据为1安全选项”,在右侧找到“网络安全:LAN管理器身份验证级别”,–选中“发送LM和NTLM响应(&)”

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号