【问题标题】:How to avoid using ApplicationContext.getBean() when implementing Spring IOC实现 Spring IOC 时如何避免使用 ApplicationContext.getBean()
【发布时间】:2013-02-13 10:33:47
【问题描述】:

我刚刚开始了解 Spring IOC 概念。我经常看到网上找到的大部分例子都是用代码来获取对象的。

ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) appContext.getBean("hello"); 

作为stackoverflow中这些问题12的参考。我推断,没有必要在代码中使用 appContext.getBean("hello") ,这被认为是不好的做法。另外,不推荐了。在这里纠正我,如果我的推断是错误的。

考虑到这一点,我对我的项目进行了相应的更改。 这是我的 applicationContext.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"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="utilClassRef" class="org.hd.derbyops.DUtils" lazy-init="false" />
<bean id="appContext" class="org.hd.derbyops.ContextProvider" lazy-init="false">
   <property name="utils" ref="utilClassRef" />
</bean>
</beans>

我的 contextProvider 类代码

public class ContextProvider implements ApplicationContextAware {

    private static ApplicationContext ctx;

    /**
     * Objects as properties
     */
    private static DUtils utils;

    public void setApplicationContext(ApplicationContext appContext)
            throws BeansException {
        ctx = appContext;

    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }

    public static DUtils getUtils() {
        return utils;
    }

    public void setUtils(DUtils dUtilsRef) {
        utils = dUtilsRef;
    }

}

例如,考虑一个依赖于 org.hd.derbyops.DUtils 的 A 类。 我正在使用以下代码行

ContextProvider.getUtils();

为了在 A 类中获取 DUtils 对象,从而避免在我的代码中的任何地方使用ApplicationContext.getBean()

假设,如果我有 10 个类,并且我的 A 类依赖于所有这些类,那么在不使用 ApplicationContext.getBean() 的情况下创建和访问其对​​象。在这种情况下,如上所述,我想创建 ContextProvider 类的属性,然后是该属性的 setter 和 getter,其中get&lt;PropertyName&gt; 是静态的。这样,我可以在需要对象的任何地方使用它,就像这样

ContextProvider.get<PropertyName>;

这是我的简短问题。 首先,我的方法对吗?如果是对的,在启动的时候加载所有的bean,会不会是性能杀手?如果不至少多次调用 getBean,您将如何在应用程序中做到这一点?

如果您要设计一个 Web 应用程序并且您要实现 Spring IOC,而无需在任何代码中使用 ApplicationContext.getBean()。你会怎么做?

注意:参考上面标记的其他问题

调用 ApplicationContext.getBean() 不是控制反转!

【问题讨论】:

  • 您是在使用 Spring MVC 还是尝试使用基本的 servlet?
  • 我没有使用 Spring MVC,只是将它用于 IOC
  • 一般来说,someone 需要从ApplicationContext 获取一个bean。理想情况下,它只会被调用一次,并且会被引导对象调用......

标签: java spring jakarta-ee inversion-of-control spring-ioc


【解决方案1】:

简单的答案是“是”和“不是”,“不是”和“不是”。最后,在网上搜索一下 spring MVC,因为这可能是你想要的。

所以,你的方法。是的,你大部分都做对了。但是,对所有事情都使用静态方法被认为是非常糟糕的做法。而且,你不需要。 Spring 的理念是您可以简单地创建普通的 pojo,并且 spring 会将它们用作单例,并将它们相互注入(它也可以动态创建对象,但我在这里讨论常见的情况)。如果你使用静态类和方法,那么:

  • 您不能模拟它们进行单元测试(您使用的是 JUnit 对吗?)
  • 您不能将它们与继承一起使用
  • 静态初始化器是释放异常的好方法
  • 等等等等

所以,是的注入,而不是静态的东西。

接下来是性能。你是对的,使用弹簧要慢得多,但是,如果你在启动时进行所有注入,它只会发生一次。 Spring 适用于可能有许多单例类传递数据的服务器端应用程序。所以,可能会有一个类从数据库中获取数据,一个类来处理它,一个类来显示它,而 spring 用于将它们连接在一起。

如果您在反复启动的应用程序中使用 spring,例如命令行应用程序,那么您将它用于错误类型的应用程序,并且您可能想要使用构建器或其他东西。 Spring 适用于不经常重启的大型企业应用程序。

最后,如果您只是在启动时将一个类的所有依赖项注入其中,并且对所有类执行此操作,那么您根本不需要执行任何 getBean 操作。此外,在 bean 上使用 init-methoddestroy-method 属性意味着您可以在 spring 完成注入依赖项后启动进程。您只需要加载上下文,您的应用就会出现(双关语)。

对于 Web 项目,Spring MVC 基本上将整个控制模式反转,并将其应用于 Web 应用程序。 spring 的东西由容器加载,你可以定义 URL 来响应,只使用 bean 名称。而且您的大部分代码都可以保留为 pojos。如果你有一些非常复杂的东西,你可能想看看 spring web flow,但我建议你在尝试之前确保你的 spring foo 非常强大。

【讨论】:

  • 在我的公司,我从未见过ApplicationContext.getBean() 之类的东西。但那是因为这些是企业级 Web 应用程序。那么究竟是什么为我加载了我所有的课程呢?是服务器做的吗?
  • 通常您会使用其中一种预装的 Spring 应用程序加载类,它们是标准的 JEE 组件,例如 servlet 等。然后这些将启动所有春季国际奥委会的工作。隐藏在这些类的内部,将调用从 XML 文件创建应用程序上下文,将其与当前运行的应用程序相关联,并以某种方式使应用程序上下文可用。
【解决方案2】:

这是我在不实际调用 ApplicationContext 上的 getBean() 的情况下获取第一个实例的示例。

public class Test{
  // Declare private static variable so that we can access it in main()
  private static Triangle triangle;

  // Use constructor injection to set the triangle
  public Test(Triangle triangle) {
      Test.triangle = triangle;
  }

  public static void main(String[] args) {
      // Specify the context file containing the bean definitions
      // Spring automatically creates instances of all the beans defined
      // in this XML file. This process is performed before you actually make
      // a getBean("beanName") call.
      ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

      // Use instance methods of triangle 
      Test.triangle.draw();
  }
} 

你可以用另一种方式:

spring.xml(您的 bean 配置 XML 文件)中

<bean class="com.example.Test" init-method="myMethod">
    <constructor-args ref="triangle"/>
</bean>

现在是你的主要课程

public class Test {
  private final Triangle triangle;

  public Test (Triangle triangle) {
     this.triangle = triangle;
  }

  public static void main (String[] args) {
     ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
  }

  // Called by Spring immediately after the Triangle Bean has been created and
  // all the properties for the bean have been set. This method name must match
  // the one specified with destroy-method attribute in spring.xml
  public void myMethod () {
     triangle.draw();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多