【问题标题】:Spring @Required & @Mandatory annotationsSpring @Required 和 @Mandatory 注释
【发布时间】:2015-02-07 14:22:37
【问题描述】:

这是 BeanClass.java

package com.practice.spring;

import org.springframework.beans.factory.annotation.Required;

import com.apress.springrecipes.sequence.Mandatory;

public class BeanClass {

    private int count;
    private String prefix;

    public BeanClass() {
        System.out.println("Default Constructor");
    }

    public BeanClass(int count, String prefix) {
        this.count = count;
        this.prefix = prefix;
        System.out.println(prefix+count);
    }

    @Required
    public void setCount(int count) {
        this.count = count;
    }

    @Mandatory
    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    @Override
    public String toString() {
        return prefix+count;
    }

}

这是 beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config />

    <bean id="beanClass1"
          class="com.practice.spring.BeanClass">
        <property name="count" value="1" />
        <property name="prefix" value="Bean" />
    </bean>
    <bean id="beanClass2"
          class="com.practice.spring.BeanClass">
        <constructor-arg value="2" />
        <constructor-arg value="Bean" />
    </bean>
    <bean id="beanClass3"
          class="com.practice.spring.BeanClass">
        <constructor-arg>
            <value>3</value>
        </constructor-arg>
        <constructor-arg>
            <value>Bean</value>
        </constructor-arg>
    </bean>
</beans>

这就是我实例化上下文的方式。

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

问题:

count 属性是必需的,前缀是必需的。如果您看到 beanClass2 我正在通过构造函数设置属性,并且在 beanClass3

但是当我执行代码时,它会抛出异常。让我困惑的重要一点是:

线程“main”中的异常 org.springframework.beans.factory.BeanCreationException:错误 创建在类路径资源中定义的名称为“beanClass2”的bean [beans.xml]:bean 初始化失败;嵌套异常是 org.springframework.beans.factory.BeanInitializationException: bean 'beanClass2' 需要属性 'count'

它打印默认构造函数和 Bean2。我也在此处粘贴整个堆栈跟踪:

2014 年 12 月 9 日晚上 8:47:33 org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO:正在刷新 org.springframework.context.support.ClassPathXmlApplicationContext@1a71e93: 启动日期 [Tue Dec 09 20:47:33 PKT 2014];上下文层次的根 2014 年 12 月 9 日晚上 8 点 47 分 33 秒 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO:从类路径加载 XML bean 定义 资源 [beans.xml] 2014 年 12 月 9 日晚上 8:47:33 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons INFO:预实例化单例 org.springframework.beans.factory.support.DefaultListableBeanFactory@4aed64: 定义 bean [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,beanClass1,beanClass2,beanClass3]; 工厂层次结构的根

默认构造函数

Bean2

2014 年 12 月 9 日 晚上 8 点 47 分 33 秒 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons INFO: 销毁单例 org.springframework.beans.factory.support.DefaultListableBeanFactory@4aed64: 定义 bean [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,beanClass1,beanClass2,beanClass3]; 工厂层次结构的根线程“main”中的异常 org.springframework.beans.factory.BeanCreationException:错误 创建在类路径资源中定义的名称为“beanClass2”的bean [beans.xml]:bean 初始化失败;嵌套异常是 org.springframework.beans.factory.BeanInitializationException: bean 'beanClass2' 需要属性 'count' org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:872) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:423) 在 org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139) 在 org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83) 在 com.practice.spring.Main.main(Main.java:13) 引起: org.springframework.beans.factory.BeanInitializationException: bean 'beanClass2' 需要属性 'count' org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.postProcessPropertyValues(RequiredAnnotationBeanPostProcessor.java:149) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1064) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) ... 11 更多

【问题讨论】:

  • 问题可能是您需要调用您的设置器,但在您的构造函数中,您要手动设置属性。如果您将构造函数更改为调用 setter,会发生什么?
  • 那有什么意义呢?我们可以通过 setter 或构造函数注入,不是吗?
  • 是的。但是您已经告诉代码必须调用 setCount,而您没有调用它。 Spring 不知道您将在您的 setter 中做什么——您可能正在做的不仅仅是设置属性;例如,您可能正在计算属性。因此,它无法知道您在构造函数中所做的事情在功能上是否等同于您所说的需要。
  • 这毫无意义@all。可以给我提供 spring ioc 文档吗?
  • 另外,基于当前的文档,@Required"将一个方法(通常是JavaBean setter方法)标记为'required':即必须将setter方法配置为依赖注入一个值。” docs.spring.io/spring/docs/current/javadoc-api/org/… 因此,您将其标记为必须注入依赖项 - 而不是注入构造函数。

标签: java spring ioc-container


【解决方案1】:

@Required 表示您使用的是 setter 注入,而不是构造函数注入。这些被设计为两个选项 - 不要同时做两个选项。

请注意 Spring 的博客中的这一点 -

@Required 允许你指示 Spring 检查 required 对你的依赖。如果您无法使用 构造函数注入,或出于任何其他原因,您更喜欢 setter 注入,@Required 是要走的路。

Setter Injection vs Constructor Injection.

最近,

@ 必需 将方法(通常是 JavaBean setter 方法)标记为 被“必需”:也就是说,setter 方法必须配置为 使用值注入依赖项。

RequiredAnnotation

因此,您将其标记为必须注入依赖项 - 而不是注入构造函数。

【讨论】:

  • 好电话。我添加了之前cmets的相关部分,包括链接。
猜你喜欢
  • 2017-02-27
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
相关资源
最近更新 更多