Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用AOP作用域代理在单例bean中自动连接原型bean_Java_Spring_Dependency Injection_Proxy_Spring Aop - Fatal编程技术网

Java 使用AOP作用域代理在单例bean中自动连接原型bean

Java 使用AOP作用域代理在单例bean中自动连接原型bean,java,spring,dependency-injection,proxy,spring-aop,Java,Spring,Dependency Injection,Proxy,Spring Aop,我能够测试在一个单例bean中自动连接一个原型bean只会导致创建一个原型bean 作为解决方案,我读到可以为原型bean定义AOP范围的代理,或者使用Spring的查找方法注入 以下是我尝试过的- PrototypeBean.java @Component @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.INTERFACES) public class Prototype

我能够测试在一个单例bean中自动连接一个原型bean只会导致创建一个原型bean

作为解决方案,我读到可以为原型bean定义AOP范围的代理,或者使用Spring的查找方法注入

以下是我尝试过的-

PrototypeBean.java

@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode =   ScopedProxyMode.INTERFACES)
public class PrototypeBean implements Prototype {

private String welcomeMessage;

public String getWelcomeMessage() {
    return welcomeMessage;
}

public void setWelcomeMessage(final String welcomeMessage) {
    this.welcomeMessage = welcomeMessage;
}
}
SingletonBean.java

@Component
public class SingletonBean implements Singleton{
@Autowired private Prototype prototype;

public Prototype getPrototype() {
    return prototype;
}

public void greet() {
    System.out.println(prototype.getWelcomeMessage());
}
}
测试班

public class AutowiredDependenciesDemo {

@Autowired private Singleton autowiredSingleton;
@Autowired ConfigurableApplicationContext context;

@Test
public void testPrototypeBeanWithAopScopedProxy(){
    Assert.assertNotNull(autowiredSingleton);

    Prototype prototypeBean = (Prototype) ((SingletonBean) autowiredSingleton).getPrototype();
    prototypeBean.setWelcomeMessage("hello world");

    autowiredSingleton.greet();

    Singleton contextSingleton = (Singleton) context.getBean("singletonBean");
    Assert.assertSame(autowiredSingleton, contextSingleton);

    Prototype anotherPrototypeBean = (Prototype) ((SingletonBean)contextSingleton).getPrototype();
    anotherPrototypeBean.setWelcomeMessage("hello india");

    contextSingleton.greet();
    autowiredSingleton.greet();
    // i expected both the prototype instances to be different. in the debugger, it does show two different 'proxied' instances. however the test fails.
    Assert.assertNotSame(prototypeBean, anotherPrototypeBean);
}

我是不是遗漏了什么?另外,对greet()方法的调用返回null。

在您对代理和原型bean的思考中,会混合一些东西

当Spring框架将原型范围的bean注入到单例范围的bean中时,它会创建一个代理对象(实现所有必需的接口)并注入它,而不是原型bean的实例。然后,每当在这个原型代理上调用该方法时,Spring都会创建一个新实例,并在这个新实例上调用该方法

在您的测试中,您只比较注入的代理,它们是相同的,因为原型Bean只有一个代理,这个代理负责在需要时创建原型Bean的新实例

以下是我的例子: 我有一个接口原型及其实现原型impl。在我的测试中,我直接从ApplicationContext获得bean类型的原型,并使用@Autowired注入它。然后在调试器中我看到:

请注意,只有一个相同的代理(查看其地址),但在此代理上调用“toString()”会显示PrototypeImpl对象的两个不同地址。这正是我上面写的

编辑:有关取消代理的信息

要通过M.Deinum扩展注释,可以通过以下方式从代理中提取基础对象:

Prototype extracted = null;

if(AopUtils.isAopProxy(a) && a instanceof Advised) {
    Object target = ((Advised)a).getTargetSource().getTarget();
    extracted = (Prototype) target;
}

是的,我也看到过类似的情况。但是,我尝试调用代理bean上的特定方法。在我的测试类中,我调用
prototypeBean.setWelcomeMessage(“hello world”)
另一个PrototypeBean.setWelcomeMessage(“你好,印度”)我曾期望Spring创建两个原型bean(它根据PrototypeBeanImpl内存地址拥有),但最后的Assert语句并不能确认我的观察结果。每次调用这个代理都会创建一个原型范围bean的新实例。如果您想要获得这样一个原型范围bean的实例并对其调用多个方法,那么您应该使用查找方法方法。它仍然是同一个代理(正如答案所解释的)。如果要比较结果对象,需要展开代理对象并获取对象的底层实际实例\