【问题标题】:How to handle @Autowire object in its parent classes?如何处理其父类中的@Autowire 对象?
【发布时间】:2020-09-21 20:52:10
【问题描述】:

我知道以前在这里被问过很多次类似的问题,但我仍然对这些机制感到困惑。

这是我的问题。来自CategoryService 中的CategoryDAO 对象的空指针异常。

@Service
public class CategoryService {
    @Autowired
    private CategoryDAO categoryDAO;

    public List<Category> list(){
        List<Category> categories = categoryDAO.list();
        for (Category category : categories){
            List<Record> rs = recordDAO.list(category.getID());
            category.setRecordNumber(rs.size());
        }
        return categories;
    }

    public void add(String name){
        Category newCategory = new Category();
        newCategory.setName(name);
        categoryDAO.add(newCategory);
    }
}
@Repository
public class CategoryDAO {
    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    public int getTotal(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<Category> categories = sqlSession.selectList("category.selectAll");

        return categories.size();
    }
}

在这个top rated postthis one 中,两个最热门的答案都提到了The most preferable option is to let Spring autowire all of your beans。 这是否意味着一旦我需要它,我还必须在其他类中自动连接CategoryService?这意味着我不能使用new 运算符来初始化一个包含自动装配对象的类? 如果是,请您解释一下背后的原因吗?

谢谢

更新

这是一个关于使用自动装配类CategoryService的示例:

public class RecordListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        RecordPanel panel = RecordPanel.getInstance();
        if (new CategoryService().list().size() == 0){
            JOptionPane.showMessageDialog(panel, "NO category is recorded, set category first");
            MainPanel.getInstance().getPanel().display(CategoryPanel.getInstance());
            return;
        }
}

CategoryService 用于new CategoryService().list().size() == 0。如果我在这里将它自动装配为此类的一个属性,那么一旦我需要它,这个类也需要注入。我想避免这种情况,这样事情会更容易。我怎样才能做到这一点?

【问题讨论】:

  • 能否提供上面提到的 NullPointer 异常的堆栈跟踪
  • @RahalKanishka 很抱歉没有第一时间提供。但是我已经按照公认的答案解决了它,现在无法获得堆栈跟踪。这只是一个基本的 NullPointer 异常,由 List&lt;Category&gt; categories = categoryDAO.list()CategoryService 类中引发。

标签: java spring


【解决方案1】:

这是否意味着一旦需要,我还必须在其他类中自动装配 CategoryService? 是的。

这意味着如果一个类包含自动装配的对象,我就不能使用 new 运算符来初始化它? 是的。

@Autowire 注释使您能够使用依赖注入。一种技术(实际上是良好实践),可以轻松更改应用程序中用于接口的实现。你定义了在属性或构造函数参数上使用@Autowire 注解时将被注入的bean/组件/服务。 无需在代码中使用new,您只需声明应将哪个具体类用于带有@Autowire 注释的接口(或者可能是类本身)。 想象一下,您创建了一个接口 RemoteAccess 和一个实现 FtpRemoteAccess,然后每次需要它时都编写 RemoteAccess remoteAccess = new FtpRemoteAccess(); 一段时间后,您可能会在几个地方结束该行。现在,如果您需要将其更改为HttpRemoteAccess,因为您有这个新的、更好的替代方案,您必须检查您的所有代码库。相反,如果您使用依赖注入,您只需更改 bean(使用 Spring 的方法不止一种)。 为了使所有这些工作,Spring 必须能够注入 bean 的所有依赖项。如果你创建一个 bean,它的所有属性也必须被注入,因为 Spring 会为你创建那个对象。

澄清:

在您的 bean(即,您将被注入的类)中,您可以使用 new 提供的有意义的对象创建对象,并且这些对象不是注入类型。你已经在CategoryService::add() 中这样做了,没关系。依赖注入并不意味着你永远不会再写new。对于将由 Spring 依赖注入 管理的对象,您只需避免使用它。 然后,还有其他一些不鼓励使用new 的良好做法,例如静态工厂方法,它建议在您的类中放置一个静态方法来构建完整的对象并让构造函数成为私有的。但是您不需要一直应用所有模式。

更新:

对于您的RecordListener 类,您必须添加一个CategoryService 属性,然后确保它已初始化。有两种选择:您可以在 bean 本身中转换 RecordListener 并在需要的地方自动装配它。这样,Spring 将构造一个 RecordListener 对象来注入它,并且还将添加任何其他需要的 bean(如 CategoryService

@Component
public class RecordListener implements ActionListener {

    @Autowire
    private CategoryService categoryService;

    @Override
    public void actionPerformed(ActionEvent e) {
        RecordPanel panel = RecordPanel.getInstance();
        if (categoryService.list().size() == 0) {
            JOptionPane.showMessageDialog(panel, "NO category is recorded, set category first");
            MainPanel.getInstance().getPanel().display(CategoryPanel.getInstance());
            return;
        }
    }
}

另一种选择是在当前创建RecordListener 的类中注入CategoryService,然后将其作为构造函数参数传递。在那种情况下,RecordListener 将不是一个 bean。

【讨论】:

  • 感谢您的解释。你能告诉我应该如何处理本地对象吗?由于@Autowire 不能应用于局部变量,并且它们不能通过new 运算符创建。我必须总是使用ApplicationContext吗?
  • 在上面添加了一个说明,因为评论太长了。
  • 感谢您的额外说明。我曾尝试使用不同的模式来处理本地对象,但 CategoryService 仍然被分配了 null。你能看看我的更新内容并给我一些详细的建议吗?
  • @chaos 您的班级CategoryService 由Spring 注入管理。请记住,您不要在托管类上使用 new。你不想写new CategoryService().list().size()。相反,您必须在需要使用它的类中添加一个带有@Autowire 注释的private CategoryService categoryService; 属性。前提是 Spring 也正在创建该类
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-09
相关资源
最近更新 更多