Bean的作用域与生命周期以及lombok的使用

目录

一、lombok的使用

二、Bean的作用域

1.Bean的六种作用域

2.单例和多例有什么区别(通过代码帮助理解区分)

3.怎么设置作用域

三、Spring的执行流程

四、Bean的生命周期


一、lombok的使用

这个对我们开发代码很有帮助,这个可以帮助减少Java代码的编写,提高开发效率。这个可以借助注解来帮我们在编译的时候自动生成相对应的getter,setter等方法。

(1)下载插件,settings-->plugins-->搜索框输入lombok。下载完成后重启项目。

(2)在pom.xml文件中添加lombok的依赖。(大家也可以去官网复制)Lombok

	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>1.18.34</version>
		<scope>provided</scope>
	</dependency>

 (3)完成前两步后,就代表我们可以去使用lombok提供的注解来简化代码了。先来了解一下lombok提供了哪些注解:(我这只举出了常用的,更多的大家可以去官网查询)

        A.@getter和@setter这两个注解可以再编译的时候帮助我们添加上getter和setter方法(这样我们就不用写了,减少了代码量);

        B.@ToString这个注解用于自动生成toString()方法,其中包含了类中的所有字段,我们可以通过exclude和of来排除或指定包含哪些字段。

        C.@NoArgsConstructor这个用于自动生成无参构造函数。

        D.@AllArgsConstructor这个注解用于生成包含所有字段的构造函数。

        E.@EqualsAndHashCode这个注解会自动生成equals和hashCode方法。

        F.@RequiredArgsConstructor这个注解会自动生成带有修饰符final或@NonNull注解的字段的构造函数。

        G.@Data这是个组合注解,可以自动生成getter,setter,toString,equals,hashCode和生成带有修饰符final或@NonNull注解的构造方法。

        H.提供了日志注解(@SLf4j、@Log4j)这个可以自动生成日志记录器实例。

        I.@NonNull这个注解会标记字段或参数非空,Lombok会生成相应的null检查代码。

(4)使用举例

二、Bean的作用域

1.Bean的六种作用域

Bean提供了6种作用域,Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式,⽐如 singleton 单例作⽤域,就 表示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他⼈修改了这个值之后,那么另⼀ 个⼈读取到的就是被修改的值。 前两种是普通Spring中的,后四种是SpringMVC中的值

1.singleton:单例作用域(Spring中Bean的默认作用域)该作用域下的Bean在IoC容器中只存在一个实例,通常我们在Bean对象属性值没有什么更改的时候才使用。

2.prototype:原型作用域(多例作用域)每次对该作用域下的Bean的请求都会创建新的实例。一般在Bean对象属性值会发生变化的时候都采用这种作用域。

3.request:请求作用域,每次http请求都会创建新的Bean实例,一次http的请求和响应才会共享Bean,类似prototype。

4.session:会话作用域,在一个http session中定义一个Bean实例。

5.application:全局作用域,在一个http servlet Context中,定义一个Bean实例。

6.websocket:Http WebSocket作用域,在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例。在Spring WebSocket项目中使用。

2.单例和多例有什么区别(通过代码帮助理解区分)

我们现在主要讨论前两种,因为我们现在针对的是普通的Spring项目,大家可以看下面这段代码,帮助大家理解单例和多例的区别。

User类

@Getter
@Setter
@ToString
public class User {
    private int id;
    private int age;
    private String name;
}


UserController类


@Controller
public class UserController {
    @Autowired
    public User user;
    public void setUser() {
        user.setAge(18);
        user.setId(1);
        user.setName("张三");
        System.out.println(user);
    }


TestController类


@Controller
public class TestController {
    @Autowired
    public User user;
    public void setUser() {
        System.out.println(user);
        user.setName("王五");
        System.out.println(user);
    }




App类


public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController = context.getBean(UserController.class);
        TestController testController = context.getBean(TestController.class);
        userController.setUser();
        testController.setUser();
    }
}

上述代码最后结果为:

这就因为Spring默认作用域为单例模式,存储到IoC容器中的为一个实例对象,所以UserController设置了值,TestController取到的值和UserController的一样,当我们在TestController对值进行更改,两个控制类中的也都会进行更改。那我们想要不进行更改怎么办呢?当然是设置作用域。

3.怎么设置作用域

设置Bean的作用域有两种方法,也就是依赖于Bean存入Spring的两种方式。如果不进行设置的话,默认就是单例模式。

(1)通过在配置文件中设置<bean>标签将Bean存入IoC中,在这个时候我们就将作用域设置好。此时作用域的设置通过字符串的方式,"prototype","singleton"。

<bean id="user" class="enity.User" scope="prototype"></bean>

(2)通过注解将其添加到IoC容器的时候,我们可以通过注解将作用域设置好。通过注解设置的时候有两种方式,一种是通过字符串,一种是通过枚举设置。

现在我们了解了怎么设置作用域,当我们对上面代码的配置文件进行修改,将User类的作用域设置为多例形式的时候,结果就变成下面这样了。

多例的作用域,每一次获取都会创建一个新的实例,所以UserController进行的操作与TestController无关。

注意!注意!即使当我们有一个类的时候,但我们存入到IoC中多个(不同的名字)我们再根据名字来获取的时候,此时默认作用域仍然是单例模式,只不过不同名字就已经成为了不同的对象。大家如果看不太懂这句话啥意思,可以私下来问问我。

三、Spring的执行流程

首先启动Spring容器(加载配置文件)->根据配置文件完成Bean的初始化(分配内存空间)->将Bean存储到Spring中(存对象)->将Bean装配到需要的类中(取对象)

四、Bean的生命周期

生命周期就是指一个对象从诞生到销毁的整个生命过程。Bean的生命周期分为5部分。

1.实例化Bean(为Bean分配内存空间)(实例化不等于初始化)

2.设置属性(Bean的注入)

3.Bean的初始化

  • 实现各种Aware通知的方法,如BeanNameAware、BeanFactoryAware、ApplicationContextAware的接口方法;
  • 执行BeanPostProcessor接口中的初始化前置方法;
  • 执行初始化方法,依赖注入操作后被执行;(初始化有两种方式一种是xml方式(在配置文件中存入Spring的时候指定init-method的方法名,在类中去实现)一种是注解方式(通过@PostConstruct表示初始化方法))
  • 执行自己指定的init-method方法(如果没写就不用管);
  • 执行BeanPostProcessor初始化后置方法。

4.使用Bean。

5.销毁Bean。销毁容器有很多种方法,如@PreDestroy(注解方式)、DisposableBean接口方法、destroy-method方法(xml方式)。

代码演示

//TeacherComponent类

@Component
//实现BeanNameAware接口,实现通知
public class TeacherComponent implements BeanNameAware, BeanPostProcessor {
    @Autowired
    public User user;
    /*
    * 初始化的通知方法
    * */
    @Override
    public void setBeanName(String s) {
        System.out.println("实现了通知,Bean的名字是:" + s);
    }
    /*
    * 初始化中的前置方法
    * */
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化前置方法");
        return bean;
    }

    /*
    * 执行初始化方法
    * */
    @PostConstruct
    public void init() {
        System.out.println("执行注解方式的初始化方法");
    }

    /*
    * 执行初始化后置方法
    * */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行初始化后置方法");
        return bean;
    }

    public void sayhi() {
        System.out.println("使用Bean,hi");
    }

    /*销毁Bean*/
    @PreDestroy
    public void destory() {
        System.out.println("销毁了Bean");
    }



//App类
public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//这里前面也用的是ClassPathXmlApplicationContext,因为我们想要看完成的生命周期,只能用这个,ApplicationContext中没有destory方法。
        TeacherComponent teacherComponent = context.getBean(TeacherComponent.class);
        teacherComponent.sayhi();
        context.destroy();
    }
}

大家的最后结果是否和我的一样呢?有没有人想过一个问题呢?我代码中明明写了前置方法和后置方法,但为啥没执行呢?前断时间查阅这个问题的时候,看到有两种解决办法觉得还不错,希望也能给你们带来帮助。

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值