java - 在 Spring 中列出方面代理的 Bean

标签 java spring-aop

有没有办法获取由 Spring 代理的特定方面的 bean 列表?

我们的某些 bean 的某个方面停止工作,我们正在尝试找出发生了什么,因此我创建了一个类来在加载 ApplicationContext 后对其进行扫描

@Component
public class AspectScanner implements ApplicationListener<ContextRefreshedEvent> {

    public static final Logger LOGGER = LoggerFactory.getLogger(AspectScanner.class);

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        final ApplicationContext applicationContext = event.getApplicationContext();
        applicationContext.[GET PROXIED BEANS CALL];
    }
}

有什么建议吗?

最佳答案

要识别建议bean,您应该检查它是否实现了org.springframework.aop.framework.Advised并使用org.springframework.aop.aspectj.AspectJPrecedenceInformation#getAspectName来获取方面名称。下面提供了概念验证代码。

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class AspectScanner implements ApplicationListener<ContextRefreshedEvent> {

    public static final Logger LOGGER = LoggerFactory.getLogger(AspectScanner.class);

    public void onApplicationEvent(ContextRefreshedEvent event) {
        final ApplicationContext applicationContext = event.getApplicationContext();
        Map<String, Object> beansOfType = applicationContext.getBeansOfType(Object.class);
        for (Map.Entry<String, Object> entry : beansOfType.entrySet()) {
            boolean advisedWith = isAdvisedWith(applicationContext, entry.getValue(), BeanAspect.class);
            LOGGER.info(entry.getKey() + (advisedWith ? " is advised" : " isn't advised"));
        }
    }

    private static boolean isAdvisedWith(ApplicationContext context, Object bean, Class<?> aspectClass) {
        boolean advisedWith = false;
        HashSet<String> names = new HashSet<>(Arrays.asList(context.getBeanNamesForType(aspectClass)));
        if (bean instanceof Advised) {
            Advisor[] advisors = ((Advised) bean).getAdvisors();
            for (Advisor advisor : advisors) {
                if (advisor instanceof AspectJPrecedenceInformation) {
                    if (names.contains(((AspectJPrecedenceInformation) advisor).getAspectName())) {
                        advisedWith = true;
                    }
                }
            }
        }
        return advisedWith;
    }


    @Aspect
    @Component
    public static class BeanAspect {

        @Before("execution(* test.AspectScanner.Bean*.*(..))")
        public void beforeAny(JoinPoint jp) {

        }

    }

    @Component
    public static class Bean1 {

        public void m() {

        }

    }

    public interface Bean2Intf {

        void m();

    }

    @Component
    public static class Bean2 implements Bean2Intf {

        public void m() {

        }

    }

    @Component
    public static class NotAdvised {

        public void n() {

        }

    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AspectScanner.class);
        context.start();
        context.registerShutdownHook();
    }

}

关于java - 在 Spring 中列出方面代理的 Bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41718212/

相关文章:

java - Tomcat中session修改的SessionListener

Spring AOP : passing target to Aspect

java - Log4j2:动态创建多个日志的日志文件

java - 当java程序通过命令提示符运行时,哪个文件被执行?

java - Java 对象的默认 hashCode() 实现

java - 如何使用 Spring AOP(AspectJ 风格)访问方法属性?

java - @Around Controller 的建议不起作用

JavaFX 使用 Platform.runLater 和 SwingUtilities.involkeLater

spring - 我们可以使用 Spring-AOP 去掉 Aspects 的 bean 定义吗?

java - 获取单个切入点中不同注释的参数