You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测含javax.faces.bean.ViewScoped的CDI Bean并终止应用启动

检测并拦截使用javax.faces.bean.ViewScoped的CDI Bean

一、运行时启动阶段检测并终止应用

利用CDI的扩展机制,在容器启动过程中扫描所有Bean,一旦发现同时标注@Named和javax.faces.bean.ViewScoped的Bean,直接抛出异常终止启动。

  1. 编写CDI扩展类
    创建一个实现Extension接口的类,在ProcessBean阶段检查Bean的注解:
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessBean;
import javax.enterprise.event.Observes;
import javax.inject.Named;
import javax.faces.bean.ViewScoped;
import java.util.Set;

public class InvalidViewScopedChecker implements Extension {

    public <T> void validateBeanScopes(@Observes ProcessBean<T> event) {
        Set<java.lang.annotation.Annotation> beanAnnotations = event.getBean().getAnnotations();
        
        boolean isNamedBean = beanAnnotations.stream()
                .anyMatch(ann -> ann.annotationType() == Named.class);
        boolean usesOldViewScoped = beanAnnotations.stream()
                .anyMatch(ann -> ann.annotationType() == ViewScoped.class);
        
        if (isNamedBean && usesOldViewScoped) {
            throw new IllegalStateException(
                "非法CDI Bean配置:" + event.getBean().getBeanClass().getName()
                + " 同时使用了@Named和javax.faces.bean.ViewScoped,该注解仅适用于JSF托管Bean,CDI Bean请使用javax.faces.view.ViewScoped"
            );
        }
    }
}
  1. 注册扩展
    在项目的META-INF/services/目录下创建文件javax.enterprise.inject.spi.Extension,将上述类的全限定名写入文件(例如com.yourpackage.InvalidViewScopedChecker)。CDI容器启动时会自动加载这个扩展,执行检测逻辑。

二、构建期提前检测(推荐)

用ArchUnit编写架构规则,在编译/测试阶段就发现问题,避免错误代码流入运行环境:

  1. 添加ArchUnit依赖(以Maven为例)
<dependency>
    <groupId>com.tngtech.archunit</groupId>
    <artifactId>archunit-junit5</artifactId>
    <version>1.2.1</version>
    <scope>test</scope>
</dependency>
  1. 编写检测规则
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import org.junit.jupiter.api.Test;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;

public class BeanScopeValidationTest {

    @Test
    void cdiNamedBeansMustNotUseOldViewScoped() {
        JavaClasses appClasses = new ClassFileImporter()
                .importPackages("com.your.app"); // 替换为你的应用包路径

        ArchRule invalidScopeRule = classes()
                .that().areAnnotatedWith(javax.inject.Named.class)
                .should().notBeAnnotatedWith(javax.faces.bean.ViewScoped.class);

        invalidScopeRule.check(appClasses);
    }
}

运行这个测试,一旦发现违规Bean,测试会直接失败,阻止构建完成。

三、IDE层面避免误导入

在IDE中配置对旧注解的警告/拦截:

  • IntelliJ IDEA:进入Settings > Editor > Inspections > Java > Deprecated API,找到javax.faces.bean.ViewScoped,将严重级别设为"Error",这样代码中出现该注解时会直接标红,并且可以禁用它的自动补全。
  • Eclipse:进入Window > Preferences > Java > Compiler > Errors/Warnings > Deprecated and restricted API,将"Forbidden reference (access rules)"设为Error,同时在Access Rules中添加规则,禁止引用javax.faces.bean.ViewScoped。

内容的提问来源于stack exchange,提问作者Adrian Jałoszewski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:14:51