【问题标题】:Spring dependency injection not workingSpring依赖注入不起作用
【发布时间】:2017-06-15 17:51:17
【问题描述】:

我的独立 Java 应用程序出现问题。问题是我正在尝试自动装配我的服务和我的 DAO,但是当我从 UI 调用服务方法时我得到一个NullPointerException,因为依赖注入无法正常工作。我尝试了很多东西,其中许多来自类似的问题,但问题仍然存在。我正在使用 Spring 4.0.6.RELEASE 和 Hibernate 4.3.11.Final。这是我的代码:

1 - 服务调用:

public class LoginView {

    @Autowired
    private UsuarioService usuarioService;
    ...
    ...
    JButton btnAutenticarse = new JButton("Autenticar");
    btnAutenticarse.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            try {
                Usuario usuario = usuarioService.login(textField.getText(),
                        String.valueOf(passwordField.getPassword()), false); // NullPointerException

            } catch (InstanceNotFoundException e1) {
     ...

2 - 服务的定义:

@Service("usuarioService")
public class UsuarioServiceImpl implements UsuarioService {

    @Autowired
    private UsuarioDao usuarioDao;
    ...

3 - DAO 的定义:

@Repository("usuarioDao")
public class UsuarioDaoHibernate extends GenericDaoHibernate <Usuario, Long>
    implements UsuarioDao {
    ...

4 - GenericDAO 的定义:

public class GenericDaoHibernate<E, PK extends Serializable> implements
    GenericDao<E, PK> {

@Autowired
private SessionFactory sessionFactory;
....

5 - AppConfig.java:

@Configuration
@ComponentScan(basePackages = "org.example.model")
public class AppConfig {

@Bean(name = "usuarioService")
public UsuarioService usuarioService() {
    return new UsuarioServiceImpl();
}

@Bean(name = "usuarioDao")
public UsuarioDao usuarioDao() {
    return new UsuarioDaoHibernate();
}

6 - spring-config.xml:

<!-- Enable usage of @Autowired. -->
<context:annotation-config/>

<!-- Enable component scanning for defining beans with annotations. -->
<context:component-scan base-package="org.example.model"/>

<!--  For translating native persistence exceptions to Spring's 
      DataAccessException hierarchy. -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/appdb" />
    <property name="username" value="username" />
    <property name="password" value="password"/>
</bean>

<bean id="dataSourceProxy" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy"
    p:targetDataSource-ref="dataSource"/>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
    <property name="dataSource" ref="dataSource"/>
    <property name="packagesToScan">
        <list>
            <value>org.example.model</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.format_sql">false</prop>
        </props>
    </property>       
</bean>

<bean id="transactionManager"  class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="persistenceExceptionTranslationPostProcessor"
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

<!-- Enable the configuration of transactional behavior based on
     annotations. -->
<tx:annotation-driven transaction-manager="transactionManager" />

【问题讨论】:

  • 如何创建LoginView
  • 这是来自另一个包 org.example.view 的 Swing 类。它有一个构造函数LoginView(),它调用一个名为initialize 的方法,其中包含抛出NullPointerException 的代码部分。
  • 我认为问题的关键在于你是用new 实例化LoginView 还是让Spring 创建LoginView。如果你使用new,Spring 不会注入这些字段。
  • 确实,我使用new 来实例化LoginView。既然这似乎是问题所在,有什么解决方法吗?将@Component 添加到LoginView 并没有解决问题。
  • 那是因为如果你使用的是new,即使你使用了组件注解,它也不是Spring托管的bean。您需要以某种方式手动注入usarioService。我用一个潜在的解决方案编辑了我的答案,但我不能说它是否一定是一个好的解决方案。

标签: java spring dependency-injection autowired


【解决方案1】:

Spring 只会在 Spring 托管 bean 中注入 Autowired 字段。 AKA 如果您使用的是 new LoginView() Spring 无法注入依赖项。

public class LoginView {

  @Autowired
  private UsuarioService usuarioService;
}

应该是

@Component
public class LoginView {

  @Autowired
  private UsuarioService usuarioService;
}

如果您不能让 Spring 管理该类,则需要以不同的方式设计它。

顺便说一句,我建议您使用构造函数注入而不是字段注入。

我可能会做的是让另一个类成为 Spring 托管 bean 并执行以下操作:

@Component
public class InitClass{

  private UsarioService usarioService;

  @Autowired
  public InitClass(UsarioService usarioService){
    this.usarioService = usarioService;
  }         

  @PostConstruct
  public void init(){
    new LoginView(usarioService);
  }         
}

然后这个类将处理您现在在@PostConstruct 中进行的所有初始化。可能需要在 @PostConstruct 中执行此操作,因为在此之前可能无法完全初始化 Spring bean。

但是,如果不了解一切是如何初始化的,就很难判断最佳策略是什么。

【讨论】:

    【解决方案2】:

    在应用程序上下文文件中进行显式组件扫描。我确实喜欢这个,它对我有用。

    <context:component-scan base-package="com.example" />
    

    您可以在链接here查看更多信息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 2023-02-24
      • 1970-01-01
      相关资源
      最近更新 更多