您的位置:首页 > 游戏 > 游戏 > Bean的作用域与生命周期以及lombok的使用

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

2024/12/21 22:29:18 来源:https://blog.csdn.net/m0_51821434/article/details/141181979  浏览:    关键词: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 {@Autowiredpublic User user;public void setUser() {user.setAge(18);user.setId(1);user.setName("张三");System.out.println(user);}TestController类@Controller
public class TestController {@Autowiredpublic 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 {@Autowiredpublic User user;/** 初始化的通知方法* */@Overridepublic void setBeanName(String s) {System.out.println("实现了通知,Bean的名字是:" + s);}/** 初始化中的前置方法* */public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("初始化前置方法");return bean;}/** 执行初始化方法* */@PostConstructpublic 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*/@PreDestroypublic 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();}
}

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com