zoukankan      html  css  js  c++  java
  • spring初始化bean时执行某些方法完成特定的初始化操作

    在项目中经常会在容器启动时,完成特定的初始化操作,如资源文件的加载等。

    一 实现的方式有三种:

    1.使用@PostConstruct注解,该注解作用于void方法上

    2.在配置文件中配置init-method方法

    <bean id="student" class="com.demo.spring.entity.Student" init-method="init2">
            <property name="name" value="景甜"></property>
            <property name="age" value="28"></property>
            <property name="school" ref="school"></property>
    </bean> 

    3.将类实现InitializingBean接口

    package com.demo.spring.entity;
    
    import javax.annotation.PostConstruct;
    
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.stereotype.Component;
    
    /**
     * @author chenyk
     * @date 2018年5月8日
     */
    @Component("student")
    public class Student implements InitializingBean{
        private String name;
        private int age;
        
        private School school;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public School getSchool() {
            return school;
        }
        public void setSchool(School school) {
            this.school = school;
        }
        
        //1.使用postconstrtct注解
        @PostConstruct
        public void init(){
            System.out.println("执行 init方法");
        }
         
        //2.在xml配置文件中配置init-method方法
        public void init2(){
            System.out.println("执行init2方法 ");
        }
        
        //3.实现InitializingBean接口
        public void afterPropertiesSet() throws Exception {
            System.out.println("执行init3方法");
        }
        
    }

    执行结果:

    执行 init方法
    2018-06-11 10:09:16,195 DEBUG [AbstractAutowireCapableBeanFactory.java:1671] : Invoking afterPropertiesSet() on bean with name 'student'
    执行init3方法
    2018-06-11 10:09:36,459 DEBUG [AbstractAutowireCapableBeanFactory.java:1731] : Invoking init method 'init2' on bean with name 'student'
    执行init2 方法

    二 实现原理:

    由以上执行结果可知:先执行@PostConstruct注解的方法,然后是实现了InitializingBean接口的afterPropertiesSet方法,最后执行在配置文件中配置的init-method方法。至于为什么是这个顺序,可以看源码:

    在 AbstractAutowireCapableBeanFactory 类中

        protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        invokeAwareMethods(beanName, bean);
                        return null;
                    }
                }, getAccessControlContext());
            }
            else {
                invokeAwareMethods(beanName, bean);
            }
    
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            }
    
            try {
           //调用初始化方法 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; }

    然后进入到 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
                            public Object run() throws Exception {
                                ((InitializingBean) bean).afterPropertiesSet();
                                return null;
                            }
                        }, getAccessControlContext());
                    }
                    catch (PrivilegedActionException pae) {
                        throw pae.getException();
                    }
                }
                else {
              //直接调用 InitializingBean 接口中的 afterPropertiesSet 方法 ((InitializingBean) bean).afterPropertiesSet(); } }
    if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
              //进入该方法可知通过反射的方式调用init-method方法 invokeCustomInitMethod(beanName, bean, mbd); } } }

    所以,初始化方法的执行顺序 afterPropertiesSet() > init-method()

    博客园的第一篇文章。感觉博客园很干净,文章排版特别是插入代码格式看起来很舒服。就不吐槽csdn了。

  • 相关阅读:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getDataSource' defined in class path resource nested exception is org.springframework.beans.factory.BeanCreat异常
    Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating Caused by: tk.mybatis.mapper.MapperException: 无法获取 cn.itcast.mapper.UserMapper.existsWithPrimaryKey 方法的泛型信息!
    fibnacci数列递归实现
    XOR加密
    Pep8课下作业
    求最大公约数伪代码
    《信息安全专业导论》第五周学习总结
    20191306《信息安全专业导论》第四周学习总结
    用或非门实现其他逻辑门
    寻找黑客偶像
  • 原文地址:https://www.cnblogs.com/51life/p/9166009.html
Copyright © 2011-2022 走看看