当前位置: 代码网 > it编程>编程语言>Java > 解决ApplicationContext获取不到Bean的问题

解决ApplicationContext获取不到Bean的问题

2024年06月10日 Java 我要评论
开发环境遇到报错org.springframework.beans.factory.nosuchbeandefinitionexception: no qualifying bean of type

开发环境遇到报错

org.springframework.beans.factory.nosuchbeandefinitionexception: no qualifying bean of type 'xxxxx' available

现将原问题代码简化抽出分析。

部署环境

  • springboot版本:1.x
  • java:1.8
  • 其他:略

问题代码

service层

  • 接口:
public interface errorbeanservice {

    void transactionalmethod();

    void callmethod();
}
  • 实现类:
@service("errorbeanserviceimpl")
public class errorbeanserviceimpl implements errorbeanservice{


    private applicationcontext applicationcontext;

    @autowired
    public void setapplicationcontext(applicationcontext applicationcontext){
        this.applicationcontext = applicationcontext;
    }

    @transactional(rollbackfor = exception.class)
    public void transactionalmethod() {
        system.out.println("transactionalmethod run ~ ");
    }


    public void callmethod() {
        // transactional注解失效
//        transactionalmethod();

        // 使用applicationcontext获取到bean 使事物注解生效
        applicationcontext.getbean(errorbeanserviceimpl.class).transactionalmethod();  // 报错行
    }
}

contro层:

@restcontroller
@requestmapping("/error")
public class errorcontroller {
    
    @autowired
    private errorbeanservice errorbeanservice;
    
    @requestmapping(value = "/errorbean", method = requestmethod.get)
    public void errorbean() {
        errorbeanservice.callmethod();
    }
}

查看报错行代码,使用了applicationcontext.getbean的方式获取bean使得内部调用事务注解生效,但在获取bean时报错nosuchbeandefinitionexception异常,报错如下:

排除了包扫描和beanname问题,看上述报错倒数第四行报错:

org.springframework.aop.framework.jdkdynamicaopproxy.invoke(jdkdynamicaopproxy.java:215)

由于使用了事物注解(aop)从而使用了动态代理,该环境使用的是jdk的动态代理机制,那么代理不会继承而是使用实现接口。

所以这个bean是通过接口注入的,就无法通过接口的实例与bean的实例关联。

ps:

  • springboot 1.x aop默认还是使用 jdk 动态代理的
  • 如果目标对象实现了接口默认采用jdk动态代理 (可强制改为cglib)
  • 如果目标对象没有实现接口默认采用cglib动态代理

解决方案

  • 升级springboot版本为2.x,aop默认使用cglib实现。
  • properties配置文件增加:spring.aop.proxy-target-class=true ## 强制使用cglib代理
  • 使用applicationcontext.getbean的重载方法获取对应的bean

修复代码

为了探求transactional注解是否生效,现增加aop 切面类模拟事物。

@aspect
@configuration
public class aopconfig {

    /**
     * 增强transactionalmethod方法 模拟transational注解
     */
    @pointcut("execution(* com.example.springbootdemo.error.test.errorbeanserviceimpl.transactionalmethod())")
    public void executeadvice() {
    }

    /**
     * 环绕增强
     */
    @around("executeadvice()")
    public object aroundadvice(proceedingjoinpoint thisjoinpoint) throws throwable {
        system.out.println("aroundadvice before proceed");
        object obj = thisjoinpoint.proceed();
        system.out.println("aroundadvice after proceed");
        return obj;
    }

}

去除事务注解:

@service("errorbeanserviceimpl")
public class errorbeanserviceimpl implements errorbeanservice{


    private applicationcontext applicationcontext;

    @autowired
    public void setapplicationcontext(applicationcontext applicationcontext){
        this.applicationcontext = applicationcontext;
    }

    public void transactionalmethod() {
        system.out.println("transactionalmethod run ~ ");
    }


    public void callmethod() {
        applicationcontext.getbean(errorbeanserviceimpl.class).transactionalmethod();
    }
}
  • 升级springboot版本为2.x 略
  • 配置配置文件 略
  • 修改callmethod方法使用getbean的重载方法

<t> t getbean(string var1, class<t> var2) throws beansexception;

代码如下:

    public void callmethod() {
        // applicationcontext.getbean(errorbeanserviceimpl.class).transactionalmethod();

        applicationcontext.getbean("errorbeanserviceimpl", errorbeanservice.class).transactionalmethod();
    }

上述三种方式最终输出结果:

aroundadvice before proceed
transactionalmethod run ~ 
aroundadvice after proceed

体悟:八股文还是有用的~

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com