【问题标题】:Using ApplicationContextAware in Bean class to initialize prototype scope bean members在 Bean 类中使用 ApplicationContextAware 来初始化原型作用域 bean 成员
【发布时间】:2019-06-06 23:51:07
【问题描述】:

我正在学习 spring,我只是在玩 ApplicationContextAware 和 bean 范围。

我将附上代码,然后描述我想要做什么。

到目前为止,我已经创建了一个

点类:

public class Point {
private int x;
private int y;

public int getX() {
    return x;
}
public void setX(int x) {
    this.x = x;
}
public int getY() {
    return y;
}
public void setY(int y) {
    this.y = y;
}

@Override
public String toString() {
    return "x: "+this.x+",y: "+this.y;
}

}

我创建了一个 Triangle 类,它有 3 个该 Point 类的实例:

public class Triangle implements ApplicationContextAware, BeanNameAware{

private Point pointA;
private Point pointB;
private Point pointC;
private String beanName;
private ApplicationContext context=null;

public Point getPointA() {
    return pointA;
}

public void setPointA(Point pointA) {
    this.pointA = (Point)this.context.getBean("point1");
}

public Point getPointB() {
    return pointB;
}

public void setPointB(Point pointB) {
    this.pointB = (Point)this.context.getBean("point2");
}

public Point getPointC() {
    return pointC;
}

public void setPointC(Point pointC) {
    this.pointC = (Point)this.context.getBean("point3");
}

public void draw() {
    System.out.println("BeanName is: "+this.beanName);
    System.out.println(pointA);
    System.out.println(pointB);
    System.out.println(pointC);
}

@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
    this.context = arg0;
}

@Override
public void setBeanName(String arg0) {
    this.beanName = arg0;
}
}

下面是spring.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 5.1.1//EN" "http://www.springframework.org/dtd/spring-beans-5.1.1.dtd">

<beans>
<bean id="triangle" class="org.java.learning.Triangle" >
    <property name="pointA" ref="point1" />
    <property name="pointB" ref="point2" />
    <property name="pointC" ref="point3" />
</bean>

<bean id="point1" class="org.java.learning.Point" scope="prototype">
    <property name="x" value="0" />
    <property name="y" value="0" />
</bean>

<bean id="point2" class="org.java.learning.Point" scope="prototype">
    <property name="x" value="20" />
    <property name="y" value="20" />
</bean>

<bean id="point3" class="org.java.learning.Point" scope="prototype">
    <property name="x" value="-20" />
    <property name="y" value="20" />
</bean>

这是主类:

public class DrawingApp {

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

        t.draw();
    }
}

所以,你会看到point1point2point3 这三个 bean 的 bean 范围是 prototype,但它们是 bean triangle 的成员,其范围默认为 singleton spring.xml

所以,我的假设是,这应该行不通,除非我能以某种方式在我的 Triangle 类中获得 ApplicationContext 并分别设置 pointApointBpointC,就像我在他们的 setter 方法中所做的那样使用ApplicationContext.

不确定这是否正确,或者这东西在实时应用程序中是否有用。

所以,如果上面的所有代码都有效,我应该得到三行输出,例如:

x: 0,y: 0
x: 20,y: 20
x: -20,y: 20

但是当我运行 main 方法时出现以下错误:

警告:上下文初始化期间遇到异常 - 取消 刷新尝试:org.springframework.beans.factory.BeanCreationException: 在类路径资源中创建名称为“三角形”的 bean 时出错 [spring.xml]:设置属性值时出错;嵌套异常是 org.springframework.beans.PropertyBatchUpdateException;嵌套的 PropertyAccessExceptions (3) 是: 属性访问异常 1: org.springframework.beans.MethodInvocationException:属性“pointA”抛出 例外;嵌套异常是 java.lang.NullPointerException 属性访问异常 2: org.springframework.beans.MethodInvocationException:属性“pointB”抛出 例外;嵌套异常是 java.lang.NullPointerException 属性访问异常 3: org.springframework.beans.MethodInvocationException:属性“pointC”抛出 例外;嵌套异常是 java.lang.NullPointerException 线程“主”中的异常 org.springframework.beans.factory.BeanCreationException:创建 bean 时出错 在类路径资源 [spring.xml] 中定义了名称“三角形”:错误 设置属性值;嵌套异常是 org.springframework.beans.PropertyBatchUpdateException;嵌套的 PropertyAccessExceptions (3) 是: 属性访问异常 1: org.springframework.beans.MethodInvocationException:属性“pointA”抛出 例外;嵌套异常是 java.lang.NullPointerException 属性访问异常 2: org.springframework.beans.MethodInvocationException:属性“pointB”抛出 例外;嵌套异常是 java.lang.NullPointerException 属性访问异常 3: org.springframework.beans.MethodInvocationException:属性“pointC”抛出 例外;嵌套异常是 java.lang.NullPointerException 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1685) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1400) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) 在 org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) 在 org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:144) 在 org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:85) 在 org.java.learning.DrawingApp.main(DrawingApp.java:9) 引起:org.springframework.beans.PropertyBatchUpdateException;嵌套的 PropertyAccessExceptions (3) 是: 属性访问异常 1: org.springframework.beans.MethodInvocationException:属性“pointA”抛出 例外;嵌套异常是 java.lang.NullPointerException 属性访问异常 2: org.springframework.beans.MethodInvocationException:属性“pointB”抛出 例外;嵌套异常是 java.lang.NullPointerException 属性访问异常 3: org.springframework.beans.MethodInvocationException:属性“pointC”抛出 例外;嵌套异常是 java.lang.NullPointerException 在 org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:122) 在 org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:77) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.app lyPropertyValues(AbstractAutowireCapableBeanFactory.java:1681) ... 13 更多

我认为我在设置 pointA、pointB 和 pointC 成员变量的值时做错了

如果我需要任何详细信息,请告诉我,以消除此错误并实现我想要做的事情。

【问题讨论】:

  • 您似乎使用了非常古老的材料。至少非常使用getBean的通用形式:getBean(Triangle.class)
  • 你为什么要这样做public void setPointB(Point pointB) { this.pointB = (Point)this.context.getBean("point2"); }。如果你通过 setter 注入,你应该有“bean-standard” setter
  • 我之前是通过 setter 注入的,但后来我尝试使用 context 对象设置值,而不是使用 setter 方法中传递的值。

标签: java spring


【解决方案1】:

您正在获得 NPE,因为上下文对象在下面和类似方法中为空

public void setPointC(Point pointC) {
    this.pointC = (Point)this.context.getBean("point3");
}

只有在所有 bean 都已初始化且上下文对象准备就绪时,才会在 ApplicationContextAware bean 中设置上下文对象。

您的代码应如下所示

public void setPointC(Point pointC) {
        this.pointC = pointC;
    }

【讨论】:

    【解决方案2】:

    与您面临的错误无关:让我们看看您的课程设置:

    您希望您的观点成为原型。所以每次你通过注入请求一个新的 Bean 时,Spring 都会给你一个新的实例。

    现在您将原型 bean 注入到默认为单例的 Triangle bean 中(这意味着它只被请求和创建一次)。所以原型 bean (Point) 也被请求一次以将它们注入到单例 Triangle bean 中。

    从现在开始,您的原型 bean 不再像原型 bean 那样工作,这意味着它们从您的 Triangle bean 继承了单例范围。

    但是在这个设置上你没问题,但你应该记住这个陷阱:Spring 只有在容器/上下文请求 bean 时才会创建原型 bean 的新实例。

    【讨论】:

    • 那么,它在这里不起作用的原因是原型bean现在也作为单例bean注入了?
    • 不,不会导致异常
    【解决方案3】:

    导致代码抛出异常的两个原因:

    • new ClassPathXmlApplicationContext("spring.xml") 方法无法意识到类上下文已准备就绪。
    • 循环依赖。创建ApplicationContext 需要成功创建所有bean,但Triangle 需要一个上下文。

    您可以使用 IOC 来解决您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-05
      • 2015-09-27
      • 1970-01-01
      • 2023-02-02
      • 1970-01-01
      • 1970-01-01
      • 2015-01-14
      • 1970-01-01
      相关资源
      最近更新 更多