【问题标题】:Loading a spring config at server startup在服务器启动时加载 spring 配置
【发布时间】:2019-12-31 18:11:14
【问题描述】:

我有一个用于识别用户的 jsp 登录页面。为了配置 JdbcTemplate ,我在 "WEB-INF/applicationContext.xml" 下使用 spring 设置了它的属性,因此为了加载 spring 上下文,我在 web.xml 中添加了一些标签。但是,在 UserDao 类中自动装配 jdbcTemplate bean 会导致 NullPointerException!

applicationContext.xml

 <context:annotation-config />
 <context:component-scan base-package="com.firstapp.dao"/>

 <bean id="datasource" 
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
     <property name="driverClassName" 
     value="oracle.jdbc.driver.OracleDriver"  />  
     <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />  
     <property name="username" value="system" />  
     <property name="password" value="oracle" />  
 </bean>  

<bean id="jdbcTemplate" 
      class="org.springframework.jdbc.core.JdbcTemplate">  
      <property name="dataSource" ref="datasource"></property>  
 </bean>  

类 DAO

 public class UserDAO 
  {
   @Autowired
   private JdbcTemplate jdbcTemplate;
   ....}

类服务

  public class UserService  
   {
      private UserDAO  userDAO  = new UserDAO ();       
    ....}

web.xml

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
  <listener-class>
     org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>

【问题讨论】:

  • UserDAO 对象是通过 Spring 还是使用 new 运算符创建的? UserDAO 类是否使用任何 spring 注释进行注释?
  • @RamPrakash UserDAO 对象被一个新的操作符实例化
  • 重复:You cannot create Spring Bean objects directly through constructor. It's not the idea of dependency injection. Wherever you need your UserDAO, you need to autowire it, or else it won't work.

标签: java spring nullpointerexception web.xml jdbctemplate


【解决方案1】:

我敢打赌,您的 UserDAO 类没有定义为 Spring Bean。在这种情况下,您有两个选择:在 XML 中定义您的 bean 或对其进行注释。

选项 1:XML

applicationContext.xml

<bean id="userDao" class="[package of UserDAO class].UserDAO">
    <property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>

在这种情况下,您不需要在现场使用@Autowired

选项 2:基于注释

applicationContext.xml

<context:annotation-config/>
<context:component-scan base-package="[package of UserDAO class]"/>

UserDAO.java

@Component
public class UserDAO {
    @Autowired
    private JdbcTemplate jdbcTemplate;
}

另请注意,不建议直接自动装配字段。你可以在here找到更多关于这个主题的信息。

DummyClass.java

@Component // must be a bean as well
public class DummyClass {
    private final UserDAO userDao;

    @Autowired
    public DummyClass(UserDAO userDao) {
        this.userDao = userDao;
    }
}

选项 3:从应用程序上下文中手动提取 Bean

我想强调的是,不推荐这种方法,你应该避免它并正确使用依赖注入。如果您需要使用该方法 - 您的应用程序的架构可能是错误的。

SpringBeanUtil.java

@Component
public class SpringBeanUtil implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }
}

UserDAO.java

public class UserDAO {
    private JdbcTemplate jdbcTemplate = SpringBeanUtil.getBean(JdbcTemplate.class);
}

【讨论】:

  • @Najla Chabeb - dominikbrandon 是绝对正确的。如果您觉得有帮助,请“点赞”并“接受”他的回答。此外,您可能对此链接感兴趣:baeldung.com/spring-boot-configure-data-source-programmatic
  • 你的意思是构造函数吗?您不能直接通过构造函数创建 Spring Bean 对象。这不是依赖注入的想法。无论您在哪里需要 UserDAO,都需要自动装配它,否则它将无法工作。
  • 你不能那样做。如果无论如何,您希望它工作,您将需要从应用程序上下文中手动提取您的 bean,但强烈不推荐这样做。请正确使用依赖注入。你可以阅读更多here
  • @NajlaChabeb 我刚刚编辑了我的答案并添加了第三个选项,这就是你要找的。这将使它为您工作。但是,我仍然鼓励您阅读有关正确使用 Spring Beans 的更多信息。
  • 在这种情况下,您需要自动装配 UserDAO 对象。当您尝试使用构造函数直接实例化 Spring Bean 时,@Autowired-annotated 字段将不会被初始化。这意味着无论何时你想使用 UserDAO 对象——你使用它的类也必须是一个 bean。
猜你喜欢
  • 2018-10-05
  • 2018-04-14
  • 1970-01-01
  • 2012-07-19
  • 2015-10-25
  • 2012-12-06
  • 1970-01-01
  • 1970-01-01
  • 2016-01-17
相关资源
最近更新 更多