【问题标题】:How getter work (Singleton Bean) in case, we inject prototype bean into singleton bean via aop scoped proxy?如果我们通过 aop 作用域代理将原型 bean 注入到单例 bean 中,getter 是如何工作的(单例 Bean)?
【发布时间】:2016-05-11 01:46:07
【问题描述】:

我的 Employee 类是 spring.xml 中定义的单例

public class Employee{
private Vehicle vehicle;
public Vehicle getVehicle() {
    return vehicle;
}
public void setVehicle(Vehicle vehicle) {
    this.vehicle = vehicle;
}
}

我有类 Vehicle,它是 spring.xml 中定义的原型

public class Vehicle {
private String name;
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
}

下面是spring.xml

<bean id="employee" class="com.example.factory.Employee">
<property name="vehicle" ref="vehicle"></property>
</bean>
<bean id="vehicle" class="com.example.factory.Vehicle" scope="prototype">
<property name="name" value="car"></property>
<aop:scoped-proxy />
</bean>

现在我知道 spring 将为车辆创建代理。每次我在员工对象上调用 getVehicle() 时,我都会得到 Vehicle 的新对象。但是在 getVehicle() 方法中,我没有创建 Vehicle 的新对象,并且根据我的理解,spring 没有为 Employee 对象创建代理。所以有人请让我详细了解内部发生了什么以及 getVehicle() 是如何工作的?

【问题讨论】:

  • 实际上getVehicle() 总是返回相同的对象,它实际上是实际Vehicle 实例的代理。对于您在Vehicle 上执行的每个方法调用,您将获得一个新实例,因为这就是您告诉它对作用域代理和scope=prototype 执行的操作。基本上,作用域代理对 scope=prototype 没有意义,仅对 requestsession 作用域(以及默认情况下未提供的其他一些)。
  • 如果getVehicle()总是返回同一个对象,那么为什么在执行System.out.println(getVehicle())这个语句时每次都会产生不同的hashcode?​​span>
  • 因为它返回一个代理而不是实际对象,所以代理总是相同的。 hashCode 方法被传递给实际的底层对象,(基本上使用hashCode 来检查它是否是同一个对象并不是一件好事,尤其是在使用代理时)。

标签: java spring proxy


【解决方案1】:

以下是我的发现

我通过删除初始化更改了车辆的 bean 定义,如下所示。

<bean id="employee" class="com.emp.Employee">
<property name="vehicle" ref="vehicle"></property>
</bean>

<bean id="vehicle" class="com.emp.Vehicle" scope="prototype">
<aop:scoped-proxy />
</bean>

我已经为这个场景创建了一个测试类

见下方代码

public class TestScope {

    @Autowired
    Employee employee = null;

    @Test
    public void testScope()
    {

        employee.getVehicle().setName("bike");
        System.out.println("vehicle name:"+employee.getVehicle().getName());


    }
    }

上面的代码运行,输出如下

vehicle name:null

但是,如果我将 Vehicle 的范围更改为默认(单例)类,我会得到以下结果

vehicle name:bike

总而言之,对于每个employee.getVehicle(),都会创建一个新的Vehicle 实例,因为它在bean 定义中明确说明要这样做,并且代理将引用这个对象。但是,如果我们删除范围定义,它将是单例的,并且将创建一个对象,并且在 bean 的整个生命周期中都将保持不变。

【讨论】:

  • 请参考link,我觉得这对这个话题更有用。
  • 嘿,这是我的问题。我知道这个。我在问spring是怎么做到的?
【解决方案2】:

您不会在每次调用 getVehicle() 时都获得一个新的 Vehicle 实例。每次 Spring 必须提供一个 Vehicle 实例时,您都会获得一个新实例。这可能通过两种方式发生:

  1. 你向 Spring 要一个 Vehicle bean
  2. Spring 将 Vehicle 自动连接到 Employee bean。这只会发生一次,因为 Employee 是一个单身人士。所以如果这是唯一的 Vehicle 的使用方式,也可以是单例。

请参阅this page 了解更详细的说明。

【讨论】:

  • 好吧,是的,不是的。它是一个作用域代理,具有作用域原型,在这种情况下,这意味着一个作用域代理被注入,Vehicle 上的每个方法调用都会导致一个新实例。这里的关键是它是一个作用域代理而不是常规原型 bean。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-14
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 2014-09-19
相关资源
最近更新 更多