spring中bean的生命周期,及生命周期中的作用 和 作用域(单例 多例)

@PostConstruct和@PreConstruct

@PostConstruct是一个Java注解,它用于指定一个方法在类实例化后调用。它的作用是在对象创建后执行一些初始化操作,例如初始化一些属性或建立一些连接。当Spring容器创建一个bean时,如果该bean的类中有一个方法被@PostConstruct注解修饰,则该方法将在bean实例化后自动调用。
@PreConstruct注解指定的方法将在bean实例化之前调用。

以下是一个示例:

@Component
public class MyComponent {
 
    private String message;
 
    @PostConstruct
    public void init() {
        message = "Hello, World!";
    }
 
    public String getMessage() {
        return message;
    }
}


在这个示例中,@PostConstruct注解修饰的init()方法在MyComponent类实例化后自动调用,并将message属性初始化为"Hello, World!"。

最近在看spring源码,所以总结下spring的生命周期和各个阶段的作用。

spring的生命周期概括起来主要如下:

  1. 实例化
  2. 属性注入 ioc注入
  3. 实现了BeanNameAware 则执行setBeanName方法 
  4. 实现了BeanFactoryAware 则执行 setBeanFactory方法,p125
  5. 实现了ApplicationContextAware 执行setApplicationContest方法 ,感觉可以参照p125
  6. BeanPostProcessor 执行postProcessBeforeInitiliaztion
  7. 实现了InitiliazingBean 执行afterPropertiesSet方法
  8. 配置文件定义了init-method 则执行对应初始化方法
  9. BeanPostProcessor 执行postProcessorfterInitilization
  10. Bean可以使用
  11. 关闭容器
  12. DisposableBean 执行destroy方法
  13. 配置文件定义了destory-method 则执行destory-method

下面进行简单的分析

1-2步进行实例化和各种属性的填充,你所用的Autowire等注解也会在这个时候生效

3-5步是执行***Aware接口中的方法,本质上就是把spring中的组件(如applicationContext,beanFactory等)通过接口的方式传给实体类,关于****Aware的接口的使用和作用以BeanFactoryAware为例:

@Component
public class PostProcessor implements BeanFactoryAware {

    BeanFactory factory;

    @Override
    // beanFactory是spring提供给你的可用BeanFactory
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        factory = beanFactory;
    }

    public  void  meythod1(){
        factory.getBean("beanName");
        System.out.println("use Bean -----");
    }

}

你的类实现了BeanFactoryAware接口,就要实现setBeanFactory方法,该方法的本质就是在实例化bean的时候,会通过setBeanFactory将beanFactory提供给你,然后你就可以使用beanFactory了。

如果想了解beanFactory和ApplicationContext的区别和关系参考这里

6和9步是BeanPostProcessor的应用

先对BeanPostProcessor的使用做出如下说明:

  • beanPostPocesser被实现并注解后,所有的bean在初始化时都会被执行所有beanPostPocessor实现类的postProcessBeforeInitialization和postProcessAfterInitialization方法,注意两个所有
  • 多个类实现了beanPostPocessor,如果存在返回为空,则会仅有一个类的postProcessBeforeInitialization方法执行了
  • 如果仅需要对某特定类处理可以在postProcessBeforeInitialization和postProcessAfterInitialization方法内使用 instanceof 方法,做针对某特定类的处理
  • 在实现的方法内修改返回的实例,即按照你的要求返回需要的代理类或者别的类,这个会在下面继续说明用法

下面看下BeanPostProcessor的实际使用:

第一个BeanPostProcessor的实现类PostProcessor

@Component
public class PostProcessor implements BeanPostProcessor,BeanFactoryAware {

    BeanFactory factory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        factory = beanFactory;
    }

    public  void  meythod1(){
        factory.getBean("contextHolder");
        System.out.println("postProcessor ---meythod1 -----");
    }

    @Override
    // 这里的o就是当前调用该方法的bean的实体类,s对应实体类的beanName
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        // 如果是PostProcessorInclude的实体类,则将实际实体类替换为PostProcessor的实体类
        // 即ac.getBean("postProcessorInclude");实际会返回PostProcessor的实体类,不再是postProcessorInclude的实体类了
        if(o instanceof PostProcessorInclude){
            System.out.println("PostProcessor-BeforeInitialization----"+s);
            return factory.getBean("postProcessor");
        }
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("postProcessor---AfterInitialization----"+s);

        return o;
    }
}

第二个BeanPostprocessor的实现类PostProcessorImpl

@Component
public class PostProcessorImpl implements BeanPostProcessor {


    public  void  meythod1(){
        System.out.println("PostProcessorNew ===do -----");
    }

    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("PostProcessorImpl---before----"+s);
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("PostProcessorImpl---after----"+s);
        return o;
    }
}

第三个类,实现了InitializingBean接口

@Component
public class PostProcessorInclude implements InitializingBean {

    public  void  meythod1(){
        System.out.println("PostProcessorInclude---meythod1---do -----");
    }

    @Override
    //此场景下,该方法不会执行,受PostProcessor的postProcessBeforeInitialization方法影响
    public void afterPropertiesSet() throws Exception {
        System.out.println("PostProcessorInclude---afterPropertiesSet");
    }
}

执行代码:


        // 上下文只需要下面一行代码就会自动调用BeanPostProcessor的方法
        ApplicationContext ac=new ClassPathXmlApplicationContext( new String[]{"applicationContext.xml"});
        Object postProcessor = ac.getBean("postProcessorInclude");
        if(postProcessor instanceof PostProcessor){
            postProcessor = (PostProcessor)postProcessor;
            ((PostProcessor) postProcessor).meythod1();
            System.out.println("说明返回代理----生效");
        }else if(postProcessor instanceof CheckUtils){
            postProcessor = (CheckUtils)postProcessor;
            ((CheckUtils) postProcessor).readProperty();
        }else if(postProcessor instanceof PostProcessorInclude){
            System.out.println("PostProcessorImpl");
            System.out.println("说明返回代理没有生效");
        }else if(postProcessor instanceof PostProcessorInclude){
            ((PostProcessorInclude) postProcessor).meythod1();
        }
结果如下:

PostProcessorImpl---before----contextHolder
postProcessor---AfterInitialization----contextHolder
PostProcessorImpl---after----contextHolder
PostProcessor-BeforeInitialization----postProcessorInclude
PostProcessorImpl---before----postProcessorInclude
postProcessor---AfterInitialization----postProcessorInclude
PostProcessorImpl---after----postProcessorInclude
PostProcessorImpl---before----org.springframework.context.event.internalEventListenerProcessor
postProcessor---AfterInitialization----org.springframework.context.event.internalEventListenerProcessor
PostProcessorImpl---after----org.springframework.context.event.internalEventListenerProcessor
PostProcessorImpl---before----org.springframework.context.event.internalEventListenerFactory
postProcessor---AfterInitialization----org.springframework.context.event.internalEventListenerFactory
PostProcessorImpl---after----org.springframework.context.event.internalEventListenerFactory
postProcessor ---meythod1 -----
说明返回代理----生效

源码中对postProcessBeforeInstantiation的解释是 给beanpostprocessor一个返回代理而不是目标bean实例的机会。

实际我在实例1中   return factory.getBean("postProcessor");这段代码生效了,ac.getBean("postProcessorInclude"),不再是返回PostProcessorImpl的实体类,而是postProcessor的实体类。

源码如下:

			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

第7步:实现了InitiliazingBean 则执行afterPropertiesSet方法,需要说明的是:

上面的代码第三个类PostProcessorInclude的afterPropertiesSet方法就不会执行。因为在postProcessBeforeInitialization方法中做了替换,不再继续向下执行,如果将return factory.getBean("postProcessor");注释掉,你会发现afterPropertiesSet方法会正常执行。

至于别的7 8 10 11 12 13就不再解释了,比较简单。

bean作用域 默认是什么?有哪些?????
默认是单例
singleton prototype request session globalSession

配置方式 

什么时候使用什么作用域?
为什么用单例或者多例?何时用?
之所以用单例,是因为没必要每个请求都新建一个对象,这样子既浪费CPU又浪费内存;
之所以用多例,是为了防止并发问题;即一个请求改变了对象的状态,此时对象又处理另一个请求,而之前请求对对象状态的改变导致了对象对另一个请求做了错误的处理;
当对象含有可改变的状态时(更精确的说就是在实际应用中该状态会改变),则多例,否则单例;
原文链接:https://blog.csdn.net/qq_36071795/article/details/83792214

他们是什么时候创建的:
1一个单例的bean,而且lazy-init属性为false(默认),在Application Context创建的时候构造
2一个单例的bean,lazy-init属性设置为true,那么,它在第一次需要的时候被构造.
3 其他scope的bean,都是在第一次需要使用的时候创建

他们是什么时候销毁的:
1 单例的bean始终 存在与application context中, 只有当 application 终结的时候,才会销毁
2 和其他scope相比,Spring并没有管理prototype实例完整的生命周期,在实例化,配置,组装对象交给应用后,spring不再管理.只要bean本身不持有对另一个资源(如数据库连接或会话对象)的引用,只要删除了对该对象的所有引用或对象超出范围,就会立即收集垃圾.
3 Request: 每次客户端请求都会创建一个新的bean实例,一旦这个请求结束,实例就会离开scope,被垃圾回收.
4 Session: 如果用户结束了他的会话,那么这个bean实例会被GC.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值