Bean的作用域和生命周期

  • Post author:
  • Post category:其他






期进





springboot





~


目录


1.Bean的作用域


1.1Bean的六大作用域


1.2设置Bean的作用域


2.Bean的执行流程


3.Bean的生命周期



1.Bean的作用域


①什么是Bean的作用域:

实质上是指Bean在spring整个框架中的某种行为模式,比如singleton单例模式,就是指Bean在整个作用域中只有一份,并且是全局共享的,当其他人在任意处修改了,那么其他人读到的就是修改后的数据。


②对①中进行示例:

(大概思路就是通过公共Bean部分来对原值进行设置,然后我们用A用户对其实行修改,并接着用B用户去进行获取,看得到的值是否一致)

(1)公共Bean的部分(我们将公共bean设置于此)

package inBean;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class Users {
    @Bean
    public User user1(){
        User user=new User();
        user.setName("张三");
        user.setId(1);
        return user;
    }
}

(2)A用户对原来数据进行修改:

package inBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
@Controller
public class UserController4 {
    @Autowired
    private User user1;
    public User getUser(){
        User user=user1;
        System.out.println("修改前的名称+ID"+user.getName()+user.getId());
        user.setId(2);
        user.setName("李四");
        return user;
    }
}

(3)B用户对修改后的数据来进行获取:

package inBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController3 {
  @Autowired
    private User user1;
  public User getUser1(){
      User user=user1;
      return  user;
  }
}

(4)main:

import inBean.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
        public static void main(String[] args) {
            //1.先获取对象的上下文
            ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
            //方式一
           UserController4 userController4=context.getBean("userController4",UserController4.class);
            System.out.println("A修改后的对象"+userController4.getUser().toString());
            UserController3 userController3=context.getBean("userController3",UserController3.class);
            System.out.println(userController3.getUser1());
        }
    }

输出结果:

我们在这里看到修改前的名字+ID分别为张三 1,但是当A用户进行修改后,B用户去获取到的值也是修改后的值。这是为什么呢?


这是因为spring中bean的默认情况下是单例模式,也就是修改后所有其他的读取到的都是修改后的值。


1.1Bean的六大作用域



①singleton:单例作用域(默认)

通常无状态(bean的状态不需要修改)下的bean就会使用该作用域,而且每一次注入的bean都是同一个bean。并且这是一种默认状态



②prototype:原型作用域(多例作用域)


原例模式实质上就是类似于多例模式,每次对该作用域下的Bean时,就会创建出新的实例。


③request:请求作用域(Spring MVC)


每次HTTP请求时就会创建出新的实例,一次HTTP请求和响应共用Bean,限于在spring MVC中使用。


④session:会话作用域(Spring MVC)


在用户会话的时候共享bean,举个例子,在你登录某个APP时,你的登录信息会被存储起来,这个时候就相当于在你登录期间,一直是在共享bean。


⑤application:全局作用域(Spring MVC)


这是关于web的上下文信息,只需了解即可。


⑥websocket: HTTP WebSocket 作用域(Spring WebSocket)



只需了解即可。


1.2设置Bean的作用域


①直接设置:

(1)方法:

使用@Scope(“prototype”),直接将其加在Bean下即可。

(2)演示:前面我们演示了默认情况下是单例模式,此时,我们就在该单例模式的基础上来实现这个@Scope(“prototype”),使其可以成为多例模式,即修改后并不影响原来的值。


②使用枚举设置:

(这里的枚举设置并不是说真的就是枚举,只是类似于这种形式罢了)

(1)方法:(这个的优势在于不容易输错)

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

(2)演示:(仍然是以上面这个例子来进行修改)


实现的是和①中同样的效果,只是方法里面参数不同罢了。


2.Bean的执行流程


①简单叙述:

当我们启动容器的时候,执行main函数时,首先会对Application中的类加载路径进行加载(spring-config.xml),紧接着会根据该xml文件中的配置扫描找到对应的包,找到对应的包后,就会开始扫描里面的spring注解,然后将Bean对象注册到容器中,这个时候如果bean对象有其他属性,也会进行读取。


②图例展示:


3.Bean的生命周期

Bean的生命周期主要分为5大过程,这里我们简单地对这五大过程进行讲解。


①实例化Bean:(买房)

实质上就是为bean分配内存空间


②设置属性:(装修)

就是指的是bean注入和配置


③Bean的初始化:(购置家具)

a.执行各种通知(执行各种 Aware)

b. 执行初始化的前置方法;

c. 执行构造方法,两种执行方式,一种是执行@PostConstruct,另一种实质性 init-method;

d. 执行初始化的后置方法;


④使用Bean(入住)


⑤销毁bean:(卖房)

a.@PreDestory

b. 重写DisposableBean接口方法

c.destroy-method

下面我们来用代码证实一下确实经过了这些过程:

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class BeanLifeComponent implements BeanNameAware {
    @PostConstruct
    public void postConstruct() {
        System.out.println("执行 @PostConstruct");
    }

    public void init() {
        System.out.println("执行 init-method");
    }

    public void use() {
        System.out.println("使用 bean");
    }


    @PreDestroy
    public void preDestroy() {
        System.out.println("执行了 @PreDestroy");
    }

    public void setBeanName(String s) {
        System.out.println("执行了 Aware 通知");
    }
}
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context =
                    new ClassPathXmlApplicationContext("spring-config.xml");
            BeanLifeComponent beanLifeComponent = context.getBean("beanLifeComponent",BeanLifeComponent.class);
            beanLifeComponent.use();
            context.destroy();
        }
    }

输出结果:

下期我们将讲解springboot相关内容~



版权声明:本文为weixin_58850105原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。