首页 > 解决方案 > 添加自定义 beanpostprocessor 并尝试获取属于类的 bean 时,没有符合条件的 bean 类型异常

问题描述

我正在学习 java 中的代理使用,并想记录方法执行的时间。

所有这些组件都放在 com.example.testproxyproject 包中。

我有 Order 接口,由 OrderImpl 类实现

命令:

@Component
public interface Order {
    String getName();
    String getVector();
    void setName(String name);
    void setVector(String vector);
}

OrderImpl 只覆盖那些方法并且不添加新的期望注解

OrderImpl:

@Component
public class OrderImpl implements Order {
    private String name;
    private String vector;
    @Time
    @Override
    public String getName() {
        return name;
    }
    @Override
    public String getVector() {
        return vector;
    }
    @Time
    @Override
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public void setVector(String vector) {
       this.vector = vector;
    }
}

时间标注很简单

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Time {
}

对于代理,我有自定义调用处理程序,我在其中测量标有时间注释的方法执行时间

public class CustomInvokeHandler implements InvocationHandler {
    private Object object;
    private List<Method> methods;
    public CustomInvokeHandler(Object object,List<Method> methods){
        this.object = object;
        this.methods = methods;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long timeBeforeInvoking = System.nanoTime();
        Object result = method.invoke(object,args);
        if(methods.stream().anyMatch(listMethod->listMethod.getName().equals(method.getName()))) {
            System.out.println(System.nanoTime()-timeBeforeInvoking);
        }
        return result;
    }
}

我在 beanPostProcessor 类中使用它

自定义Bean处理器:

@Component
public class CustomBeanProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> beanClass = bean.getClass();
        if (beanClass.getInterfaces().length == 0) return bean;
        return Proxy.newProxyInstance(beanClass.getClassLoader(), beanClass.getInterfaces(), new CustomInvokeHandler(bean, getAnnotatedMethods(bean.getClass().getMethods(), Time.class)));
    }
    public <T extends Annotation>List<Method> getAnnotatedMethods(Method[] methods, Class<T> annotation){
        return Stream.of(methods).filter(method-> method.isAnnotationPresent(annotation)).collect(Collectors.toList());
    }
}

在演示应用程序中,我测试了我的自定义 beanpostprocessor

@Configuration
@ComponentScan("com.example.testproxyproject")
public class DemoApplication {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext(DemoApplication.class);
        Order order = context.getBean(Order.class);
        order.setName("new Name");
        System.out.println(order.getName());
    }
}

结果: 在此处输入图像描述

当我运行它时它应该可以正常工作,但是如果我将需要的 bean 更改为 OrderImpl 类,我会得到这个异常

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.testproxyproject.OrderImpl' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
    at com.example.testproxyproject.DemoApplication.main(DemoApplication.java:12)

标签: javaspringaopspring-aopdynamic-proxy

解决方案


正是您将依赖项声明为接口而不是实现类的原因:您将原始 bean 替换OrderImpl为不再是OrderImpl. 其他类型的建议也会发生完全相同的事情。


推荐阅读