当前位置: 首页 > 知识库问答 >
问题:

如何在spring bean上强制/验证spring scope注释

万博涛
2023-03-14

此外,如果spring bean中有@autowire注释,那么是否有一种方法可以验证注入的bean是否具有正确的作用域。我的假设是,如果您将原型作用域bean注入到单例作用域bean中,很可能这不是您想要的。虽然在某些用例中,这是开发人员想要的,但在我们的案例中,到目前为止,这主要是开发人员的错误。

共有1个答案

夏涵畅
2023-03-14

您可以使用AspectJ的能力来基于切入点声明错误和/或警告。

免责声明:我从来没有使用过Spring,所以我不是那里的专家,只是编了一个没有太多示范意义的例子。

具有原型作用域的Spring bean:

package de.scrum_master.app;

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

@Component
@Scope("prototype")
public class ScopedBean {}
package de.scrum_master.app;

import org.springframework.stereotype.Component;

@Component
public class UnscopedBean {}
package de.scrum_master.app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class BeanWithAutowire {
    //@Autowired
    private ScopedBean scopedBean;

    @Autowired
    public BeanWithAutowire(ScopedBean scopedBean) {
        this.scopedBean = scopedBean;
    }

    @Autowired
    public void setScopedBean(ScopedBean scopedBean) {
        this.scopedBean = scopedBean;
    }
}

静态注释一致性检查的方面:

package de.scrum_master.aspect;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

public aspect BeanAnnotationChecker {
    declare error :
        @annotation(Component) && !@annotation(Scope) :
        "Spring component without scope declaration found";

    declare error :
        execution(@Autowired *.new(.., @Scope("prototype") *, ..)) && within(@Scope("singleton") *) :
        "singleton bean auto-wired into prototype container via constructor";

    declare error :
        execution(@Autowired * *(.., @Scope("prototype") *, ..)) && within(@Scope("singleton") *) :
        "singleton bean auto-wired into prototype container via setter method";

    declare error :
        set(@Autowired * *) && within(@Scope("singleton") *) :
        "singleton bean auto-wired into prototype container via field assignment";
}

使用AspectJ编译器的Maven POM:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.scrum-master.stackoverflow</groupId>
    <artifactId>aspectj-fail-build</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>AspectJ - fail build for wrong/missing annotations</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.source-target.version>1.7</java.source-target.version>
        <aspectj.version>1.8.4</aspectj.version>
        <main-class>de.scrum_master.app.ScopedBean</main-class>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>${java.source-target.version}</source>
                        <target>${java.source-target.version}</target>
                        <!-- IMPORTANT -->
                        <useIncrementalCompilation>false</useIncrementalCompilation>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>aspectj-maven-plugin</artifactId>
                    <version>1.7</version>
                    <configuration>
                        <showWeaveInfo>true</showWeaveInfo>
                        <source>${java.source-target.version}</source>
                        <target>${java.source-target.version}</target>
                        <Xlint>ignore</Xlint>
                        <complianceLevel>${java.source-target.version}</complianceLevel>
                        <encoding>UTF-8</encoding>
                        <verbose>true</verbose>
                    </configuration>
                    <executions>
                        <execution>
                            <!-- IMPORTANT -->
                            <phase>process-sources</phase>
                            <goals>
                                <goal>compile</goal>
                                <goal>test-compile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>org.aspectj</groupId>
                            <artifactId>aspectjtools</artifactId>
                            <version>${aspectj.version}</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>${aspectj.version}</version>
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.0.7.RELEASE</version>
        </dependency>
    </dependencies>

</project>

MVN clean包的控制台输出:

(...)
[INFO] ------------------------------------------------------------------------
[INFO] Building AspectJ - fail build for wrong/missing annotations 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
(...)
[ERROR] singleton bean auto-wired into prototype container via constructor
    C:\Users\Alexander\Documents\java-src\SO_AJ_MavenFailBuildOnWrongAnnotation\src\main\java\de\scrum_master\app\BeanWithAutowire.java:14
public BeanWithAutowire(ScopedBean scopedBean) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[ERROR] singleton bean auto-wired into prototype container via setter method
    C:\Users\Alexander\Documents\java-src\SO_AJ_MavenFailBuildOnWrongAnnotation\src\main\java\de\scrum_master\app\BeanWithAutowire.java:19
public void setScopedBean(ScopedBean scopedBean) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[ERROR] Spring component without scope declaration found
    C:\Users\Alexander\Documents\java-src\SO_AJ_MavenFailBuildOnWrongAnnotation\src\main\java\de\scrum_master\app\UnscopedBean.java:6
public class UnscopedBean {}
             ^^^^^^^^^^^

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
(...)
 类似资料:
  • 我有一个spring rest服务,它接受Person对象。Person对象具有名称、电话号码和电子邮件。当添加一个人时,电话号码是强制性的。如果存在电话号码属性,它将使用或或验证是否为空。但是如果属性不存在,验证就不起作用。请建议提供任何验证注释,以检查JSON请求中是否存在该属性。 以下是请求体测试用例 {“name”:“anu”,“phonenumber”:“”,“email”:“test@

  • 问题内容: 是否有一个静态分析工具可以在IDE外部运行一致地强制使用@Override注释?CheckStyle具有MissingOverride检查,但仅适用于使用@inheritDoc Javadoc标记的方法。我正在寻找一种可以在连续集成计算机上的新构建配置中运行的工具。 问题答案: 一种方法是使用TeamCity的“检查”运行器。我不确定它是否真的可以在IDE之外运行,因为它是在Intel

  • 问题内容: 我获得了用于Web推送的Firebase Cloud Messaging注册令牌。然后,我将此邮件发送到服务器以保存在数据库中,以供以后推送。但是,如何验证此令牌有效或伪造的? 我已经尝试过了,但是我认为这是针对Auth令牌而不是针对Web推送的。 其他人可以将随机伪造令牌的请求发送到我的服务器。我想防止这种情况,然后再保存到数据库中。 编辑:已解决,我编写了一个简单的类来使用FCM快

  • 本文向大家介绍js如何验证密码强度,包括了js如何验证密码强度的使用技巧和注意事项,需要的朋友参考一下 验证“密码强度”的例子很常见,我们注册新的账号的时候往往设置密码,此时就遇到验证密码强度的问题了。“密码强度”也就是密码难易程度的意思。 原理: 1、如果输入的密码为单纯的数字或者字母:提示“低” 2、如果是数字和字母混合的:提示“中”  3、如果数字、字母、特殊字符都有:提示“强” 下面是一种

  • 问题内容: 在某些条件下,在我的Django应用中,我希望能够强制用户使用用户名注销。不一定是当前登录的用户,而是另一个用户。因此,我认为request方法没有关于我要注销的用户的任何会话信息。 我熟悉django.auth和auth。注销方法,但是它将请求作为参数。如果我只有用户名,是否存在“ Django方式”将用户注销?还是我必须推出自己的注销SQL? 问题答案: 我认为Django中尚无认

  • 我想验证属性firstName和lastName。但我不想每次都重复注释。 如何创建自定义注释,使代码如下所示 验证也是一样的