gpt4 book ai didi

java - Java Spring @Autowired无法按预期工作

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:36:37 27 4
gpt4 key购买 nike

由于@Autowired,我的应用程序未按预期运行。
是否因为下面的代码?

@PropertySource("WEB-INF/config.properties")
public class DBQuery {
@Autowired
private Environment env;

我尝试了2天的大量可用解决方案和示例,但没有希望让我的应用程序正常运行。非常感谢那些可以使用我的代码纠正我的人。

错误消息
2016-12-15 14:23:04 WARN  XmlWebApplicationContext:487 - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dbQuery' defined in ServletContext resource [/WEB-INF/test-servlet.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.lang.String]: : No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

尝试以下下面的解决方案后更新了完整堆栈错误消息
<bean id="dbQuery" class="com.cdmDP.db.DBQuery" >
<constructor-arg type="java.lang.String" value="1"/>
</bean>

2016-12-15 15:46:49 ERROR ContextLoader:331 - Context initialization failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DBQuery' defined in file [D:\program_files\apache-tomcat-8.0.39\webapps\test\WEB-INF\classes\com\test\db\DBQuery.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.lang.String]: : No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1139)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1042)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4853)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:753)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:729)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:940)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1816)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 28 more

com / test / ViewAllData.java
@Controller
public class ViewAllData {
DBQuery dbQuery;

@Autowired
public ViewAllData(DBQuery dbQuery){
this.dbQuery = dbQuery;
}

@RequestMapping("/viewAllData")
public ModelAndView viewData() throws SQLException, ClassNotFoundException{
String dataTable;
ResultSet rs = dbQuery.getAllData();
//processing

return new ModelAndView("viewAllData", "message", dataTable);
}
}

com / test / db / DBQuery.java
@Controller
@Service
@PropertySource("WEB-INF/config.properties")
public class DBQuery {
@Autowired
private Environment env;
String dbUsername = env.getProperty("db.username");
String dbPassword = env.getProperty("db.password");
String dbUrl = env.getProperty("db.url");

String start;
@Autowired
public DBQuery(String start) throws ClassNotFoundException, SQLException{
this.start = start;
}

public ResultSet getAllDataPassport() throws SQLException, ClassNotFoundException{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);

Statement statement = conn.createStatement();
String sql = "select * from testing_table";
ResultSet rs = statement.executeQuery(sql);

return rs;
}

}

test-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="com.test, com.test.db" />
<context:annotation-config />

<bean id="viewAllData" class="com.test.ViewAllData"/>
<bean id="dbQuery" class="com.test.db.DBQuery" >
<property name="start" value="1"/>
</bean>

<bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource">
<property name="basename" value="messages" />
</bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>

</beans>

最佳答案

您的代码有多种缺陷。

  • 您的配置存在缺陷,因为不了解注释并将其与XML混合
  • 您应该使用DataSource来处理Connection对象,并在使用
  • 后正确释放它们
  • 控制器
  • 中不应包含SQL处理代码
  • 不应在控制器
  • 中构造HTML

    您已经使用带有参数的构造函数定义了 DBQuery类,并使用 @Autowired对此构造函数进行了注释。这意味着Spring将尝试创建 DBQuery的实例(由于您的 <context:component-scan />),并尝试在您的上下文中找到 String类型的bean。该bean不在那里,因此失败了。

    此外,由于组件扫描以及XML中存在一个实例,您最终会得到 DBQuery的多个实例。删除XML配置。组件也可以是 @Service@Controller,但不能同时是两者。非 @PropertySource类上的 @Configuration不会执行任何操作。

    话虽如此,并假设您主要想使用批注,请先删除 @Autowired构造函数,然后简单地创建 setStart方法。除此以外,它更像是 @Repository
    @Repository
    public class DBQuery {

    @Autowired
    private Environment env;
    String dbUsername = env.getProperty("db.username");
    String dbPassword = env.getProperty("db.password");
    String dbUrl = env.getProperty("db.url");
    String start;

    public ResultSet getAllDataPassport() throws SQLException, ClassNotFoundException{
    Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);

    Statement statement = conn.createStatement();
    String sql = "select * from testing_table";
    ResultSet rs = statement.executeQuery(sql);

    return rs;
    }
    }

    当然,还要从XML中删除 DBQuery bean以及 ViewAllData bean的bean。这些由 <context:component-scan />检测和创建

    现在,您应该直接在代码中使用 DriverManager并将其注入到类中,而不是直接使用 DataSource

    将以下内容添加到您的XML配置中。
    <context:property-placeholder location="WEB-INF/config.properties" />

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
    </bean>

    注意:尽管 DriverManagerDataSourceDataSource,但不要在生产中使用它。在这种情况下,请使用正确的连接池,例如 HikariCP。这里的好处是您可以配置它,并保留 DBQuery不变。

    现在,无需注入 Environment和所有属性,只需将 DataSource注入到 DBQuery对象中即可。
    @Repository
    public class DBQuery {

    private final DataSource dataSource;

    @Autowired
    public DBQuery(DataSource dataSource) {
    this.dataSource=dataSource;
    }

    public ResultSet getAllDataPassport() throws SQLException {

    Connection conn = this.dataSource.getConnection();
    Statement statement = conn.createStatement();
    String sql = "select * from testing_table";
    ResultSet rs = statement.executeQuery(sql);
    return rs;
    }
    }

    但是,此代码仍然存在缺陷,因为您没有关闭 ConnectionResultSet(除非您在控制器中执行此操作,这会使它更加有缺陷)。您的 getAllDataPassport应该应该返回 List对象(或 Passport)的 DataPassport。因此,您需要将控制器的部分处理/转换移至 DBQuery

    为了简化使用JDBC的工作,Spring可能需要使用[ JdbcTemplate]而不是 DataSource来编写代码,因为这将为您管理资源关闭和异常处理。您可以很容易地使用 RowMapper将每一行转换为 Passport对象。

    在您的xml中添加以下内容
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
    </bean>

    并将其注入您的 DBQuery而不是 DataSource
    @Repository
    public class DBQuery {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public DBQuery(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
    }

    public List<Passport> getAllDataPassport() {

    String sql = "select * from testing_table";
    return this.jdbcTemplate.query(sql, new PassportRowMapper());
    }
    }

    上面的代码将执行您的查询,获取并关闭资源,并将行转换为 Passport对象。当然,您需要编写 PassportRowMapper才能将每一行转换为 Passport
    public class PassportRowMapper implements RowMapper<Passport> {

    public Passport mapRow(ResultSet rs, int rowNum) throws SQLException {
    Passport p = new Passport();
    p.setNumber(rs.getString(1));
    // further logic to get row information
    return p;
    }
    }

    注意:请勿在 rs.next中执行 RowMapper,而 JdbcTemplate会解决此问题。您只需要将一行转换为 Passport即可。

    现在,您的控制器不再需要进行转换,而不再依赖于SQL。为了进行测试,您现在可以轻松模拟 DBQuery并对 ViewAllData控制器进行单元测试。
    @Controller
    public class ViewAllData {

    private final DBQuery dbQuery;

    @Autowired
    public ViewAllData(DBQuery dbQuery){
    this.dbQuery = dbQuery;
    }

    @RequestMapping("/viewAllData")
    public ModelAndView viewData() {
    String dataTable;
    List<Passport> passports = dbQuery.getAllDataPassports();
    // List to whatever it needs to be
    return new ModelAndView("viewAllData", "message", dataTable);
    }
    }

    看起来在您的控制器中,您正在将 List<Passport转换为 String,我担心它包含HTML表。您不应该那样做,在它所属的视图中应该具有这种逻辑。

    在控制器中,将项目列表添加到模型中。
        @RequestMapping("/viewAllData")
    public ModelAndView viewData() {
    String dataTable;
    List<Passport> passports = dbQuery.getAllDataPassports();
    // List to whatever it needs to be
    return new ModelAndView("viewAllData", "passports", passports);
    }

    现在,在您的视图中,您可以使用JSTL遍历集合并创建HTML表。
    <table>
    <c:forEach items="${passports}" var="passport">
    <tr><td>${passport.number}</td><!-- other columns --></tr>
    </c:forEach>
    </table>

    现在,您已将视图,模型和控制器分离。您现在甚至可以使用同一控制器将其导出为PDF,Excel或JSON。无需更改。

    最后的技巧是使用 InternalResourceViewResolver而不是普通的 UrlBasedViewResolver。具有更多功能,自动检测JSTL可以节省一些配置。
    <bean id="viewResolver" class="org.springframework.web.servlet.view. InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
    </bean>

    关于java - Java Spring @Autowired无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41158209/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com