首页 > 试题广场 >

下面有关spring的依赖注入,说法错误的是?

[单选题]
下面有关spring的依赖注入,说法错误的是?
  • 依赖注入通常有如下两种:设置注入和构造注入:
  • 构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入
  • 当设值注入与构造注入同时存在时,先执行设值注入,再执行构造注入
  • 设值注入是指IoC容器使用属性的setter方法来注入被依赖的实例。这种注入方式比较简单、直观

spring依赖注入有如下几种方式:
①setter方式注入(设值注入)
②构造器方式注入
    Spring支持利用构造器注入参数实例化Bean方式。只要在Spring的配置文件中增加构造器参数constructor-arg
    Spring就会自动的调用有参数的构造器创建bean对象实例, 整个过程无需程序编码只需要配置applicationContext.xml文件即可
③自动装配功能实现属性自动注入
Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系,autowire可以针对单个bean进行设置,
autowire的方便之处在于减少xml的注入配置。
在xml配置文件中,可以在<bean/>元素中使用autowire属性指定自动装配规则,一共有五种类型值:



发表于 2015-09-09 10:11:39 回复(6)

注入方式:

接口注入

属性注入[属性的SET/GET]

构造注入[构造方法注入]

使用构造函数依赖注入时,Spring保证所有一个对象所有依赖的对象先实例化后,才实例化这个对象。使用set方法依赖注入时,Spring首先实例化对象,然后才实例化所有依赖的对象。

当设值注入与构造注入同时存在时,先执行设置注入,在执行构造注入。

发表于 2014-11-21 20:23:02 回复(4)
特意花了时间一步步调试了,C选项还真不是这样呢,org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(String, RootBeanDefinition, Object[])这个方法里,生成BeanWrapper的时候,最终委托org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(String, RootBeanDefinition, Object[])去实例化对象。若有构造器参数即在xml配置文件中有
bean节点下有构造器配置的,就会委托于org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(String, RootBeanDefinition, Constructor<?>[], Object[])最终委托于org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(String, RootBeanDefinition, Constructor<?>[], Object[])
请看:
public BeanWrapper autowireConstructor(
 final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) {

 BeanWrapperImpl bw = new BeanWrapperImpl();
 this.beanFactory.initBeanWrapper(bw);

 Constructor<?> constructorToUse = null;
 ArgumentsHolder argsHolderToUse = null;
 Object[] argsToUse = null;

 if (explicitArgs != null) {
 argsToUse = explicitArgs;
 }
 else {
 Object[] argsToResolve = null;
 synchronized (mbd.constructorArgumentLock) {
 constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
 if (constructorToUse != null && mbd.constructorArgumentsResolved) {
 // Found a ***d constructor...
 argsToUse = mbd.resolvedConstructorArguments;
 if (argsToUse == null) {
 argsToResolve = mbd.preparedConstructorArguments;
 }
 }
 }
 if (argsToResolve != null) {
 argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
 }
 }

 if (constructorToUse == null) {
 // Need to resolve the constructor.
 boolean autowiring = (chosenCtors != null ||
 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
 ConstructorArgumentValues resolvedValues = null;

 int minNrOfArgs;
 if (explicitArgs != null) {
 minNrOfArgs = explicitArgs.length;
 }
 else {
 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
 resolvedValues = new ConstructorArgumentValues();
 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
 }

 // Take specified constructors, if any.
 Constructor<?>[] candidates = chosenCtors;
 if (candidates == null) {
 Class<?> beanClass = mbd.getBeanClass();
 try {
 candidates = (mbd.isNonPublicAccessAllowed() ?
 beanClass.getDeclaredConstructors() : beanClass.getConstructors());
 }
 catch (Throwable ex) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 "Resolution of declared constructors on bean Class [" + beanClass.getName() +
 "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
 }
 }
 AutowireUtils.sortConstructors(candidates);
 int minTypeDiffWeight = Integer.MAX_VALUE;
 Set<Constructor<?>> ambiguousConstructors = null;
 List<Exception> causes = null;

 for (int i = 0; i < candidates.length; i++) {
 Constructor<?> candidate = candidates[i];
 Class<?>[] paramTypes = candidate.getParameterTypes();

 if (constructorToUse != null && argsToUse.length > paramTypes.length) {
 // Already found greedy constructor that can be satisfied ->
 // do not look any further, there are only less greedy constructors left.
 break;
 }
 if (paramTypes.length < minNrOfArgs) {
 continue;
 }

 ArgumentsHolder argsHolder;
 if (resolvedValues != null) {
 try {
 String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
 if (paramNames == null) {
 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
 if (pnd != null) {
 paramNames = pnd.getParameterNames(candidate);
 }
 }
 argsHolder = createArgumentArray(
 beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
 }
 catch (UnsatisfiedDependencyException ex) {
 if (this.beanFactory.logger.isTraceEnabled()) {
 this.beanFactory.logger.trace(
 "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
 }
 if (i == candidates.length - 1 && constructorToUse == null) {
 if (causes != null) {
 for (Exception cause : causes) {
 this.beanFactory.onSuppressedException(cause);
 }
 }
 throw ex;
 }
 else {
 // Swallow and try next constructor.
 if (causes == null) {
 causes = new LinkedList<Exception>();
 }
 causes.add(ex);
 continue;
 }
 }
 }
 else {
 // Explicit arguments given -> arguments length must match exactly.
 if (paramTypes.length != explicitArgs.length) {
 continue;
 }
 argsHolder = new ArgumentsHolder(explicitArgs);
 }

 int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
 argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
 // Choose this constructor if it represents the closest match.
 if (typeDiffWeight < minTypeDiffWeight) {
 constructorToUse = candidate;
 argsHolderToUse = argsHolder;
 argsToUse = argsHolder.arguments;
 minTypeDiffWeight = typeDiffWeight;
 ambiguousConstructors = null;
 }
 else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
 if (ambiguousConstructors == null) {
 ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
 ambiguousConstructors.add(constructorToUse);
 }
 ambiguousConstructors.add(candidate);
 }
 }

 if (constructorToUse == null) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 "Could not resolve matching constructor " +
 "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
 }
 else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 "Ambiguous constructor matches found in bean '" + beanName + "' " +
 "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
 ambiguousConstructors);
 }

 if (explicitArgs == null) {
 argsHolderToUse.storeCache(mbd, constructorToUse);
 }
 }

 try {
 Object beanInstance;

 if (System.getSecurityManager() != null) {
 final Constructor<?> ctorToUse = constructorToUse;
 final Object[] argumentsToUse = argsToUse;
 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
 @Override
 public Object run() {
 return beanFactory.getInstantiationStrategy().instantiate(
 mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
 }
 }, beanFactory.getAccessControlContext());
 }
 else {
 beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
 mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
 }

 bw.setWrappedInstance(beanInstance);
 return bw;
 }
 catch (Throwable ex) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
 }
 }

这段先是调用构造方法,然后再进行setter
发表于 2015-01-29 16:09:04 回复(4)
大家可以自己尝试一下,首先执行的是构造器,然后是setter
发表于 2015-07-05 11:22:13 回复(0)
Spring的依赖注入:
依赖注入通常有如下两种:设置注入和构造注入:
构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入
设值注入是指IoC容器使用属性的setter方法来注入被依赖的实例。这种注入方式比较简单、直观

发表于 2016-11-26 09:34:15 回复(0)
感觉C的表述有点问题。对于同一个对象来说,如果存在构造注入,会先执行构造注入的,然后再对其进行设值注入。对于整个注入流程而然,在执行构造注入的时候会调用其他依赖的Bean的getBean方法,这时会触发另一个构造注入和设值注入。不知道题中表述的设值注入在前是什么意思?感觉怎么说都合理呢。
Spring完成一个Bean的构造大致分为三步,第一步是从XML文件读取我们对Bean的定义,然后放在BeanDefition对象中,第二步是构造一个空的对象,这个时候就相当于我们在编程的时候new一个对象,如果有工厂方法,会调用工厂方法构造对象,如果存在构造注入方法,就会调用构造注入,否则使用默认的空的构造方法构造一个对象;第三步是依赖注入的过程,如果这时候有定义依赖注入,就会反射setter方法。
所以C选项是对的,它们分别发生在第二步和第三步。
编辑于 2015-09-01 22:42:14 回复(0)
这答案不合理····
怎么可能没有调用构造器就调用setter?
要是不限调用构造器,对象都没,setter个鸡蛋啊。
发表于 2015-03-20 20:53:04 回复(2)
先执行构造注入,即执行构造函数创建对象,有了对象才可以调用setter方法.
发表于 2020-02-18 12:34:52 回复(0)
这个是beanfactory中bean的声明周期,来自精通spring企业开发实战。图中表示先进行bean的实例化,它是根据配置情况调用构造函数或者工厂方法实例化。在构造注入中,就是通过传入构造函数需要的参数然后执行构造函数进行实例化。图中的设置属性值,就是将bean所配置的属性值设置到bean对应的属性中去,对应着属性注入(设置注入)。所以bean的初始化过程中先进行的构造函数实例化,再进行的属性配置。
    我实验的方式是 在一个bean中配置构造注入和属性注入,但是两次注入对属性的赋值不同,然后getBean,看属性值是哪个,就说明后执行哪个注入方式。不知道配置bean的时候配置顺序是否有影响,所以我调换两种注入的顺序,再次进行getBean,查看结果。两次结果都是显示的属性注入所配置的值。
    不知道我这样实验对不对,希望大家指正!
发表于 2017-09-12 08:52:24 回复(0)
C 是正确的,当设值注入与构造注入同时存在时,先执行构造注入,在执行设置注入。
发表于 2017-06-21 21:17:36 回复(1)
spring4
debug的时候先执行构造注入
再执行setter注入
发表于 2017-01-24 11:29:02 回复(0)
答案是C
先执行 设值 注入,再执行构造注入
发表于 2015-07-17 09:38:55 回复(2)
 public class TestBean {
    private String name;
    private int age;
    public TestBean()
    {
        System.out.println("TestBean - -- -no Param");
    }
    public TestBean(String name)
    {
        System.out.println("=================" + name + "=================");
        this.name = name;
    }
    public void setAge(int age) {
        System.out.println("设置age");
        this.age = age;
    }
}  <bean id="testBean" class="TestBean">
        <constructor-arg name="name" value="adea"></constructor-arg>
        <property name="age" value="12"></property>
    </bean> 
以上是一个实例bean ,我配置了构造器注入和设置注入两种
结果是:
=================adea=================
设置age

我测试的是spring4.0.0.release版本,所以C应该是对的,而B没理解什么意思,是指构造器注入顺序吗?那不是应该由构造器本身决定吗?
发表于 2015-06-21 09:18:44 回复(1)
C  在没有设值注入的情况下才会根据配置文件中的构造注入,一旦有设值注入,则构造注入失效
发表于 2015-04-11 14:47:44 回复(3)

有设值注入和构造注入同时存在时,设值注入有效

发表于 2019-11-05 09:14:25 回复(0)
这道题4个选项都是对的
发表于 2019-06-18 10:10:25 回复(0)
这题怎么选了c??c是错的??? 还记得老师问我们:”spring配置文件中,有构造注入和setter注入同时存在时,运行时是先执行set方法还是先执行构造方法?” 某些同学:“先执行构造…” 老师:“你怎么知道?宁可说'我不知道,但我可以去下断点测试一下',也不要自作聪明。” 然后我们下断点,测试出来是set方法先执行!这可是断点测的!
发表于 2019-05-03 20:14:24 回复(0)
C
发表于 2019-05-01 18:26:41 回复(0)
C
发表于 2019-05-01 09:19:18 回复(0)
依赖注入怎么只有两种?
发表于 2019-04-26 20:22:35 回复(0)