并发多线程环境下触发spring3的getBean的一个bug, bean的scope为prototype

 

并发多线程环境下, 触发spring3的getBean的一个bug, bean的scope为prototype(在spring-framework-3.0.0.RELEASE和spring-framework-3.0.3.RELEASE测试过)。

 

bug见:https://jira.springsource.org/browse/SPR-7423
svn源码提交号为:3603;revised constructor argument caching for highly concurrent creation scenarios (follow-up to SPR-7423)
bug在3.0.4版本被修正。

bug修正(具体修改请看spring svn源码):
1。把volatile方式调整为同步方式来保证代码正确性与健壮性:
去除RootBeanDefinition中resolvedConstructorOrFactoryMethod、constructorArgumentsResolved、resolvedConstructorArguments、preparedConstructorArguments的四个属性修饰符volatile,增加constructorArgumentLock对象在访问上述四个属性相关代码对constructorArgumentLock加synchronized来保证同步。
2。涉及org/springframework/beans/factory中的以下类:
RootBeanDefinition.java
DefaultListableBeanFactory.java
AbstractAutowireCapableBeanFactory.java
ConstructorResolver.java
SimpleInstantiationStrategy.java

 

concurrent get bean test will be java.lang.NullPointerException:

 

frist/Person.java文件:

/**
 *
 */
package first;

/**
 * person bean
 *
 * @author yangwm Aug 5, 2010 11:20:16 AM
 */
public class Person {
    private String name;
    private int age;
    private String hobby;
   
    public Person(String name, int age, String hobby) {
        this.name = name;
        this.age = age;
        this.hobby = hobby;
    }
   
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Person{name=");
        sb.append(name);
        sb.append(", age=");
        sb.append(age);
        sb.append(", hobby=");
        sb.append(hobby);
        sb.append("}");
        return sb.toString();
    }
   

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getHobby() {
        return hobby;
    }
    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
   
}

 

frist/first.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.0.xsd">

    <bean id="person" name="person"
        class="first.Person" scope="prototype">
        <constructor-arg value="yangwm" type="String" />
        <constructor-arg value="25" type="int" />
        <constructor-arg value="basketball" type="String" />
    </bean>
</beans>

 

first/GetPersonTest.java文件:

/**
 *
 */
package first;

import java.io.IOException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * concurrent get bean test will be java.lang.NullPointerException
 *
 * @author yangwm Jun 12, 2010 1:31:50 PM
 */
public class GetPersonTest {
   
    /** get spring bean container applicationContext **/
    private static final ApplicationContext context = new ClassPathXmlApplicationContext("first/first.xml");

    public static void main(String[] args) throws IOException {
        for (int i = 0; i < 1000; i++) {
            new Thread(new PersonRun(i)).start();
        }
    }

    /**
     * concurrent get bean test runnable
     *
     * @author yangwm Jun 15, 2010 3:40:18 PM
     */
    static class PersonRun implements Runnable {
        int id;

        public PersonRun(int id) {
            this.id = id;
        }
       
        public void run() {
            System.out.println("Thread " + id + " start..." + System.currentTimeMillis());
            try {
                Person people = (Person) context.getBean("person");
                System.out.println(Thread.currentThread().getName() + " people.toString()=" + people.toString());
            } catch (Exception e) {
                System.err.println(Thread.currentThread().getName() + "-----------------------------------------");
                e.printStackTrace();
                System.exit(0);
            }
            System.out.println("Thread " + id + " end..." + System.currentTimeMillis());
        }
       
    }
   
}

运行抛出异常:

 

。。。。。

Thread 75 end...1280993191703
Thread-100 people.toString()=Person{name=yangwm, age=25, hobby=basketball}
Thread 100 end...1280993191703
Thread-71 people.toString()=Person{name=yangwm, age=25, hobby=basketball}
Thread 71 end...1280993191703Thread-80-----------------------------------------
java.lang.NullPointerException
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:669)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:194)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:993)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:897)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1075)
    at first.GetPersonTest$PersonRun.run(GetPersonTest.java:43)
    at java.lang.Thread.run(Thread.java:717)
Thread-143-----------------------------------------
java.lang.NullPointerException
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:669)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:194)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:993)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:897)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1075)
    at first.GetPersonTest$PersonRun.run(GetPersonTest.java:43)
    at java.lang.Thread.run(Thread.java:717)
Thread-141-----------------------------------------
java.lang.NullPointerException
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:669)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:194)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:993)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:897)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1075)
    at first.GetPersonTest$PersonRun.run(GetPersonTest.java:43)
    at java.lang.Thread.run(Thread.java:717)
Thread-130-----------------------------------------
java.lang.NullPointerException
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:669)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:194)

 

 

 

 

 

 

 

 

你可能感兴趣的:(并发多线程环境下触发spring3的getBean的一个bug, bean的scope为prototype)