spring bean的生命周期

spring bean的生命周期

ApplicationContextAware接口

当一个类实现了这个接口之后,这个类就可以方便地获得ApplicationContext对象

Spring发现某个Bean实现了ApplicationContextAware接口,Spring容器会在创建该Bean之后,自动调用该Bean的setApplicationContextAware()方法,调用该方法时,会将容器本身ApplicationContext对象作为参数传给该方法。

InitializingBean 接口

当一个类实现这个接口之后,Spring启动时,初始化Bean时,若该Bean实现InitializingBean接口,则会自动调用afterPropertiesSet()方法,完成一些用户自定义的初始化操作。

全生命周期样例:

package com.check;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

/**
 * @author lin.hongwen
 * @date 2021-02-05
 * @Description
 */
@Service
public class LhwTest implements ApplicationContextAware,InitializingBean,BeanNameAware,BeanFactoryAware,BeanPostProcessor,DisposableBean {
    private static final Logger LOG = LogManager.getLogger(LhwTest.class);
    private ApplicationContext applicationContext;

    @Override
    public void setBeanName(String var1) {
        //顺序1 获取bean的名字。值是lhwTest
        String beanName = var1;
        LOG.info("setBeanName=="+beanName);
    }

    @Override
    public void setBeanFactory(BeanFactory var1) {
        //顺序2 获取bean示例工厂
        BeanFactory beanFactory = var1;
        LOG.info("setBeanFactory=="+beanFactory);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //顺序3 获取上下文
        this.applicationContext = applicationContext;
        LOG.info("setApplicationContext=="+applicationContext);
    }

    @Override
    public void afterPropertiesSet() {
        // 顺序4 已经完成了所有bean基础信息的封装
        // 这时候可以获取spring上下文,获取所有bean的信息
        String names[]=applicationContext.getBeanDefinitionNames();
        LOG.info("afterPropertiesSet");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        // 顺序5 对每个已经封装好基础信息的bean进行 准备开始实例化
        LOG.info("postProcessBeforeInitialization.bean=="+bean);
        LOG.info("postProcessBeforeInitialization.beanName=="+beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 顺序5 已经完成bean的实例化
        LOG.info("postProcessAfterInitialization.bean=="+bean);
        LOG.info("postProcessAfterInitialization.beanName=="+beanName);
        return bean;
    }

    @Override
    public void destroy() {
   //不知道有啥用 LOG.info(
"destroy"); } }

样例:

e.g获取spring上下文,并根据上下文内容。过滤method,判断返回值是否符合要求

package com.lhw

import java.lang.reflect.Method;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;

@Service
public class StandardCheck implements ApplicationContextAware,InitializingBean {
    private static final Logger LOG = LogManager.getLogger(StandardCheck.class);
    private ApplicationContext applicationContext;
    //不用检查的方法
    @Value("${uncheckLogMethod}")
    private String uncheckLogMethod;
    //是否开启检查
    @Value("${standardCheckFlag}")
    private String standardCheckFlag;
    
    private String[]uncheckLogMethods;
    
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    //获取上下文
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
      //在spring初始化后调用此方法
        if(LOG.isInfoEnabled()) {
            LOG.info("standardCheckFlag={}",standardCheckFlag);
            LOG.info("uncheckLogMethod={}",uncheckLogMethod);
        }
        if("true".equals(standardCheckFlag)) {
            if(StringUtils.isNotBlank(uncheckLogMethod)&&!"${uncheckLogMethod}".equals(uncheckLogMethod)) {
                uncheckLogMethods=uncheckLogMethod.split(",");
            }
            loadApiFromSpringBeans();
        }
    }
    
    private void loadApiFromSpringBeans(){
        //获取spring上下文
        String names[]=applicationContext.getBeanDefinitionNames();
        
        for(String name:names){
            //获取这个类
            Class<?>type = applicationContext.getType(name);
            //获取类的相对路径名称
            String className = type.getName();
            if(StringUtils.isNotBlank(className)) {
                if(className.startsWith("com.controller")) {
                    if("com.BaseController".equals(className)) {
                        continue;
                    }
                    //获取父类,要求所有类必须继承com.BaseController
                    Class<?>superClass = type.getSuperclass();
                    if(superClass != null) {
                        if(!"com.BaseController".equals(superClass.getName())) {
                            throw new RuntimeException(type.getSuperclass().getName()+"["+className+"]必须继承com.BaseController");
                        }
                    }
                    
                    //获取注解,要求所有类必须有@Controller、@RestController、@Api注解
                    if(type.getAnnotation(Controller.class)==null&&type.getAnnotation(RestController.class)==null) {
                        throw new RuntimeException("["+className+"]必须有Controller或RestController的注解");
                    }
                    if(type.getAnnotation(Api.class)==null) {
                        throw new RuntimeException("["+className+"]必须有io.swagger.annotations.Api的注解");
                    }
                    
                    //获取类下的已声明的方法
                    Method methods[] = type.getDeclaredMethods();
                    if(methods != null){
                        boolean checkFlag = true;
                        for(Method method:methods){
                            //获取方法的返回值
                            Class<?>returnType = method.getReturnType();
                            if(method.getAnnotation(RequestMapping.class)!=null) {
                                //带有@RequestMapping的注解才需要检查
                                //判断方法的返回值是否合规
                                if(!"com.ResultData".equals(returnType.getName())) {
                                    throw new RuntimeException("["+className+"."+method.getName()+"]必须返回com.ResultData");
                                }
                                //判断这个方法是否需要检查其他内容
                                String methodFullName = className+"."+method.getName();
                                if(uncheckLogMethods!=null) {
                                    for(String um:uncheckLogMethods) {
                                        if(methodFullName.equals(um)) {
                                             checkFlag = false;
                                            break;
                                        }
                                    }
                                }
                                if(checkFlag) {
                                    //需要检查,检查该方法所需要的其他注解
                                    OperationLog operLog = method.getAnnotation(OperationLog.class);
                                    if(operLog==null) {
                                        throw new RuntimeException("["+className+"."+method.getName()+"]必须增加OperationLog注解");
                                    }
                                }
                            }
                        }
                    }
                }
            }
            
        }
    }
    
}
原文地址:https://www.cnblogs.com/linhongwenBlog/p/14378760.html