Spring中注入bean时的scope属性详解、往singleton中注入prototype属性的bean以及Spring使用注解实现AOP切面编程

一、Spring中注入bean时的scope属性详解以及往singleton中注入prototype属性的bean

官方文档上提到Spring中scope属性可以有以下取值:

1. singleton : (Default) Scopes a single bean definition to a single object instance for each Spring IoC container.

singleton (单一实例)容器中创建时只存在一个实例,也就是单例模型。

2. prototype : Scopes a single bean definition to any number of object instances.

prototype 容器在输出bean对象时,每次都会重新生成一个新的对象给请求方。

3. request : Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.

request 容器XmlWebApplicationContext 会为每个HTTP请求创建一个全新的RequestPrecessor对象,请求结束该对象的生命周期结束,可以认为在浏览器每次刷新都会生成一个新的bean。

4. session : Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.

session 可以理解为用户的登录信息,Spring容器会为每个独立的session创建属于自己的全新的实例,比request存活更长时间。可以理解为一个用户使用浏览器请求每次刷新时都是相同的bean.

5. application : Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.

ServletContext(web应用)中的单例,在一个web应用中,可能会有多个ApplicationContext,所以,application不等于singleton(singleton是容器中的单例)。可以理解为不同的用户刷新同一个请求(调用同一个application)都是相同的bean.

**6. websocket :**Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext。即WebSocket的完整生命周期中将创建并提供一个实例。

虽然属性值不少,不过常用的也就是singleton和prototype。除了在配置文件中设置scope属性外,还可以在类中使用scope注解实现。request,session和global session只用于web程序,比如和XmlWebApplicationContext共同使用。

如下示例,而如果在非WEB程序中使用request就会报异常:Exception in thread "main" java.lang.IllegalStateException: No Scope registered for scope name 'request'

java 复制代码
package com.kermit.test;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype")
//@Scope("singleton")
//@Scope("request")
public class HelpTool {
    public String getString(){
        return "spring.";
    }
}

另外注意到spring文档中1.5.3.关于Singleton Beans with Prototype-bean Dependencies的描述:

When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus, if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.

However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container instantiates the singleton bean and resolves and injects its dependencies. If you need a new instance of a prototype bean at runtime more than once, see Method Injection。

即要在一个singleton的bean中注入一个prototype的bean,这个prototype的bean只会初始化一次,因为在注入操作时prototype的bean已经完成了初始化,因为prototype的作用不会生效。如果要让这prototype生效,可以使用Method Injection方法注入。

二、Spring使用注解实现AOP切面编程

Spring使用注解实现AOP切面编程首先需要导入一些包,在测试的时候,我开始使用@Aspect注解时,就是找不到 import 包,后来发现是缺少包:aspectj 导致的问题。我这里导入的包如下:

XML 复制代码
<dependencies>
	<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>5.3.39</version>
	</dependency>

	<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
	<dependency>
		<groupId>org.aspectj</groupId>
		<artifactId>aspectjweaver</artifactId>
		<version>1.9.9</version>
		<scope>runtime</scope>
	</dependency>

	<!-- https://mvnrepository.com/artifact/aspectj/aspectjrt -->
	<dependency>
		<groupId>aspectj</groupId>
		<artifactId>aspectjrt</artifactId>
		<version>1.5.4</version>
	</dependency>
</dependencies>

ApplicationContext.xml 配置文件中需要添加上注解支持的配置,在使用 <aop:aspectj-autoproxy /> 配置时,其有一个属性 proxy-target-class="" 值默认为False 即为使用JDK实现注解,如果修改为True,则表示使用cglib来实现,但这些对用户无感,也无须关注,知道即可。

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--注解AOP-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

切入的方法类及注解内容如下代码所示:

java 复制代码
package com.kermit.aoptest;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class DiyLog  {

    @Before(value = "execution(* com.kermit.aoptest.Article.*(..))")
    public void before(){
        System.out.println("do before method");
    }

    @After(value = "execution(* com.kermit.aoptest.Article.*(..))")
    public void after(){
        System.out.println("do after method");
    }

}

被切入的类方法代码如下:

java 复制代码
package com.kermit.aoptest;

import org.springframework.stereotype.Component;

import java.sql.SQLOutput;
@Component
public class Article implements ArticleInterface{
    @Override
    public void insert() {
        System.out.println("insert one record.");
    }

    @Override
    public void update() {
        System.out.println("update one record.");
    }
}
相关推荐
_Evan_Yao7 小时前
Redis 缓存穿透、击穿、雪崩,一次讲清!
java·spring·mybatis
梓豪csd7 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼7 小时前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
thefool1122668 小时前
TCP 1
java·1024程序员节
金銀銅鐵10 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
AI人工智能+电脑小能手11 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务
paopaokaka_luck12 小时前
心理咨询管理系统(WebSocket实时沟通、基于用户的协同过滤、 ECharts多维分析、 预约业务流程、预约校验与定时处理)
java·vue.js·spring boot·mysql·spring·echarts·1024程序员节
2301_322414280413 小时前
springboot农产品交易平台的设计与实现08055-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·spring boot·redis·mysql·tomcat·maven·mybatis
考虑考虑13 小时前
JDK26的JEP 500属性
java·后端·java ee
LMT流氓兔14 小时前
第五单元——第十二课:把脚本整理成项目
java·数据库·python·langchain·1024程序员节