有没有办法获取由 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/