25 Spring Classic test questions you'll face a few? Detailed interviews circular dependencies

Foreword

Take a look at what is the cycle of dependence
when a ClassA is dependent on ClassB, and ClassB in turn depend ClassA, thus creating a cycle of dependence:
ClassA -> ClassB -> ClassA
circular dependencies -> two or more bean holding each other the other, forming a closed loop.
the Spring scene in a cyclic dependency:
1, in dependence upon the configuration of the cycle. (Spring can not do anything)
2, setter circular dependencies:
circulation field attribute setter dependent manner [single case, the default mode -> find Bean Bean relies on the current through the recursive method, and then will be placed in the cache Cach in advance [up] . By early exposure -> early exposure to a exposedObject return for exposure Bean. ]
Spring Bean object is first instantiated no argument constructor dependency [---]> and then set the object attributes
Spring first instantiates a builder Bean object -----> end instantiated objects into a Map , and this is not provided Spring provide access attribute of the object instance reference method. Examples of binding we look ,, Spring instantiated when A, B, C, will be followed to set the properties of the object, in which case A depends B, it will go to the single Example B Map removed exists inside the object, to such a push, not out of circulation problems myself.

Said the following about Spring is that if the resolve circular dependencies

The first: circular configuration parameters dependent
Bean Spring container will each identifier being created in a "current creates Bean Pool", in the process of creating the identifier Bean remains in the pool.
So if you find yourself already in the "Bean created the current pool" where will throw an exception BeanCurrentlyInCreationException represents a circular dependency in Bean creation process; and for the Bean is created from the "current creation Bean Pool" removed.
First we initialize three Bean.

public class StudentA {

    private StudentB studentB ;

    public void setStudentB(StudentB studentB) {
        this.studentB = studentB;
    }

    public StudentA() {
    }

    public StudentA(StudentB studentB) {
        this.studentB = studentB;
    }
}
public class StudentB {

    private StudentC studentC ;

    public void setStudentC(StudentC studentC) {
        this.studentC = studentC;
    }

    public StudentB() {
    }

    public StudentB(StudentC studentC) {
        this.studentC = studentC;
    }
}
public class StudentC {

    private StudentA studentA ;

    public void setStudentA(StudentA studentA) {
        this.studentA = studentA;
    }

    public StudentC() {
    }

    public StudentC(StudentA studentA) {
        this.studentA = studentA;
    }
}

OK, the above is a very basic three classes ,, StudentA is configured with a reference StudentB. StudentB There are arguments constructor is StudentC, StudentC there are arguments constructor is StudentA, thus creating a cycle of dependency situation,
we have these three Spring Bean to manage, and use a reference structure instantiated.

<bean id="a" class="com.zfx.student.StudentA">
        <constructor-arg index="0" ref="b"></constructor-arg>
    </bean>
    <bean id="b" class="com.zfx.student.StudentB">
        <constructor-arg index="0" ref="c"></constructor-arg>
    </bean>
    <bean id="c" class="com.zfx.student.StudentC">
        <constructor-arg index="0" ref="a"></constructor-arg>
    </bean> 

The following is a test class:
public class {the Test

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("com/zfx/student/applicationContext.xml");
        //System.out.println(context.getBean("a", StudentA.class));
    }
}

The results being given the information as follows:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: 
    Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?

If we understand the beginning of that sentence, then this error should not be surprised, Spring container to create a singleton StudentA, StudentA rely StudentB, then A on the "current creation Bean Pool", then create StudentB, StudentB rely StudentC, then the B in "Creating Bean current pool" in this case create StudentC, StudentC in turn depends studentA, but this time has been Student in the pool, it will be an error in the Bean ,, because the pool is not completely initialized, it will depend on the error, (initialization finished Bean will be removed from the pool)
the second: setter single way of example, the default mode
if the mode setter injection to say, then, we'd better look at a Spring Bean instantiated in Fig.

FIG front two steps that: Spring Bean after a first object is instantiated and then set the object attributes

Modify the configuration file to set the injection mode

<!--scope="singleton"(默认就是单例方式)  -->
    <bean id="a" class="com.zfx.student.StudentA" scope="singleton">
        <property name="studentB" ref="b"></property>
    </bean>
    <bean id="b" class="com.zfx.student.StudentB" scope="singleton">
        <property name="studentC" ref="c"></property>
    </bean>
    <bean id="c" class="com.zfx.student.StudentC" scope="singleton">
        <property name="studentA" ref="a"></property>
    </bean>

Here is the test class:

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("com/zfx/student/applicationContext.xml");
        System.out.println(context.getBean("a", StudentA.class));
    }
}

Print results:

`com.zfx.student.StudentA@1fbfd6`

Why not set the way of it being given?
We combine goes above chart, with the first configuration example of the Spring Bean object, this time will Spring instantiation objects into the end of a Map, and a method of obtaining this Spring provides attribute is not set instantiated object reference .
Combined with our example ,, look when Spring instantiates StudentA, StudentB, after StudentC, will be followed to set the properties of the object, this time dependent StudentB studentA, StudentB singleton object exists inside the Map will be to remove, to such a push, not out of circulation problems myself,
Here is the method Spring in the source code. The following classes of source DefaultSingletonBeanRegistry.java the Spring Bean package

/ * The Cache Objects of Singleton: the bean name -> the bean instance (singleton instance of the Map cache set of objects) /
Private Final the Map <String, Object> = new new singletonObjects of ConcurrentHashMap <String, Object> (64);

/** Cache of singleton factories: bean name --> ObjectFactory(单例的工厂Bean缓存集合) */
private final Map<String, ObjectFactory> singletonFactories = new HashMap<String, ObjectFactory>(16);

/** Cache of early singleton objects: bean name --> bean instance(早期的单身对象缓存集合) */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

/** Set of registered singletons, containing the bean names in registration order(单例的实例化对象名称集合) */
private final Set<String> registeredSingletons = new LinkedHashSet<String>(64);
/**
 * 添加单例实例
 * 解决循环引用的问题
 * Add the given singleton factory for building the specified singleton
 * if necessary.
 * <p>To be called for eager registration of singletons, e.g. to be able to
 * resolve circular references.
 * @param beanName the name of the bean
 * @param singletonFactory the factory for the singleton object
 */
protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

**第三种:setter方式原型,prototype**
修改配置文件为:

<bean id="a" class="com.zfx.student.StudentA" scope="prototype">
<property name="studentB" ref="b"></property>
</bean>
<bean id="b" class="com.zfx.student.StudentB" scope="prototype">
<property name="studentC" ref="c"></property>
</bean>
<bean id="c" class="com.zfx.student.StudentC" scope="prototype">
<property name="studentA" ref="a"></property>
</b
```ean>


scope="prototype" 意思是 每次请求都会创建一个实例对象。
两者的区别是:有状态的bean都使用Prototype作用域,无状态的一般都使用singleton单例作用域。
测试用例:

the Test class {public
public static void main (String [] args) {
the ApplicationContext the ClassPathXmlApplicationContext context = new new ( "COM / ZFX / Student / the applicationContext.xml");
// this case must obtain an instance management Spring, because now scope = "prototype" only when requested by the object instance will
System.out.println (context.getBean ( "a", StudentA.class));
}
}


打印结果:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?



为什么原型模式就报错了呢?
对于“prototype”作用域Bean,Spring容器无法完成依赖注入,因为“prototype”作用域的Bean,Spring容器不进行缓存,因此无法提前暴露一个创建中的Bean。

# 大家可以再回过头来看看以下Spring面试题,你自己能答对几道呢?
1 、什么是 Spring  框架?Spring  框架有哪些主要模块?
2 、使用 Spring  框架能带来哪些好处?
3 、什么是控制反转(IOC) ?什么是依赖注入?
4 、请解释下 Spring  框架中的 IoC ?
5 、BeanFactory 和 和 ApplicationContext  有什么区别?
6 、Spring  有几种配置方式?
7 、如何用基于 XML  配置的方式配置 Spring ?
8 、如何用基于 Java  配置的方式配置 Spring ?
9 、怎样用注解的方式配置 Spring ?
10 、请解释 Spring Bean  的生命周期?
11 、Spring Bean  的作用域之间有什么区别?
12 、什么是 Spring inner beans ?
13 、Spring  框架中的单例 Beans  是线程安全的么?
14 、请举例说明如何在 Spring  中注入一个 Java Collection ?
15 、如何向 Spring Bean  中注入一个 Java.util.Properties 
16 、请解释 Spring Bean  的自动装配?
17 、请解释自动装配模式的区别?
18 、如何开启基于注解的自动装配?
19 、请举例解释@Required  注解?
20 、请举例解释@Autowired  注解?
21 、请举例说明@Qualifier  注解?
22 、构造方法注入和设值注入有什么区别?
23 、Spring  框架中有哪些不同类型的事件?
24 、FileSystemResource 和 和 ClassPathResource  有何区别?
25 、Spring  框架中都用到了哪些设计模式?

**欢迎大家一起交流,喜欢文章记得点个赞,感谢支持!**

Guess you like

Origin blog.51cto.com/14442094/2424661