Как применить / проверить аннотацию объема пружины на бобах весны

1

Мы полностью отслеживаем аннотации и не используем файлы XML для конфигурации пружин.

Значение по умолчанию для весенних фасолей - это одноэлементный режим, который многие разработчики забывают и в конечном итоге создают бобы, которые должны быть по-разному охвачены. Добавлена сложность проблем сочетания и сопоставления различных видов бобов.

Есть ли какой-либо плагин maven, который может проверить, имеет ли какой-либо класс, который имеет аннотацию @Component также аннотацию @Scope и сбой сборки, если она отсутствует. Это заставит разработчиков задуматься о масштабах и шаблонах использования. Если что-то подобное не существует, я могу написать плагин или создать собственный инструмент, который может проверить это и сжечь во время сборки jenkins. Может ли какой-нибудь весенний код помочь мне сделать это?

Кроме того, если в весеннем @Autowire аннотация @Autowire, есть ли способ проверить, что @Autowire бобовые имеют правильные области. Я работаю с предположением, если вы введете прототип бокового участка в одномодовый бобы, скорее всего, это не то, что вы wan. Хотя могут быть случаи, когда это то, что хочет разработчик, в нашем случае до сих пор это в основном ошибка разработчика.

  • 0
    Я не знаю, как сделать проверку с помощью Spring. Вы можете сделать это с помощью пользовательского правила PMD или FindBugs.
  • 0
    Вы могли бы взглянуть на maven -forcer-plugin, где вы можете реализовать свое собственное правило, которое может быть для вас путем ...
Теги:
maven
spring
dependency-injection

3 ответа

0
Лучший ответ

Вы можете использовать функцию AspectJ для объявления ошибок и/или предупреждений на основе pointcut.

Отказ от ответственности: я никогда не использовал Spring, поэтому я не являюсь экспертом и просто составляю пример без особого смысла для демонстрации.

Весенняя фасоль с прототипом:

package de.scrum_master.app;

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

@Component
@Scope("prototype")
public class ScopedBean {}

Spring bean с отсутствующим объявлением:

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";
}

Maven POM с использованием компилятора AspectJ:

<?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 package :

(...)
[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] ------------------------------------------------------------------------
(...)

Я думаю, что пример несколько ясен, за исключением синтаксиса AspectJ, но вы можете прочитать больше об этом в руководствах или учебниках AspectJ. Если вы раскомментируете аннотацию @Autowired в объявлении поля, вы увидите еще больше ошибок для явных присвоений полей. Однако AspectJ не может совпадать с простым объявлением поля (без назначения). Поэтому всякий раз, когда ваши разработчики полагаются на аннотации полей вместо аннотированных конструкторов или методов setter, т.е. У вас нет явного назначения полей в вашем коде, ошибки компиляции не будет. Вы можете обойти это, сопоставляя методы getter или доступ к полям в вашем коде для косвенного соответствия по полям. Не стесняйтесь спросить, как это сделать, если вы не можете понять это сами.

0

Недавно мне также нужно было проверить область @Autowired beans и не удалось найти подходящее решение. Таким образом, я создал небольшой проект, который позволяет проверять области видимости компонентов во время выполнения. По умолчанию он допускает следующие инъекции:

  • Синглтоны можно вводить во все
  • Все может быть введено в прототипы
  • Прокси AOP можно вводить во все
  • Все может быть введено в бобы того же масштаба

Если вы хотите разрешить загрузку bean-компонента в другую область видимости, это должно быть явно разрешено с помощью соответствующей аннотации:

@Bean
@Scope("prototype")
@InjectableInto("singleton")
MyBean getMyBean(){
 //...
} 

Если компонент во время выполнения использует зависимости недопустимой области видимости, он может либо регистрировать его, либо вызывать исключение (и тем самым предотвращать создание компонента), либо выполнять какие-либо пользовательские действия.

0

Простейшей идеей, которую я могу придумать, является использование проверки Checkstyle RegexpSinglelineJava для обеспечения 1 и только 1 из @Scope для каждого файла: http://checkstyle.sourceforge.net/config_regexp.html#RegexpSinglelineJava

Поскольку вам нужно проверить наличие двух аннотаций, возможно, будет проверена проверка RegexpMultiline (для этого потребуются упорядоченные аннотации): http://checkstyle.sourceforge.net/config_regexp.html#RegexpMultiline

Ещё вопросы

Сообщество Overcoder
Наверх
Меню