java Spring @Autowired 不工作并返回 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27840860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:29:36  来源:igfitidea点击:

Spring @Autowired not working and returning null

javaspringemailjavamail

提问by Haozhe Xie

I have problems on @Autowiredin Spring:

@Autowired在 Spring遇到问题:

MailSender.java

邮件发送器

package com.example.package.util;

@Component
public class MailSender {
    @Autowired
    public MailSender(VelocityEngine velocityEngine, JavaMailSender mailSender) {
        this.velocityEngine = velocityEngine;
        this.mailSender = mailSender;
    }

    public void send() {
        // Dosomething
    }

    private final VelocityEngine velocityEngine;

    private final JavaMailSender mailSender;
}

MailService.java

邮件服务程序

package com.example.package.service;

@Service
public class MailService {
    public void sendEmail(String email) {
        // mailSender is always null
        String mailBody = mailSender.send();
    }

    // Autowired here is not working
    @Autowired
    @Qualifier("myMailSender")
    private MailSender mailSender;

    // Autowired here is working
    @Autowired
    private UserDao userDao;
}

Configuration

配置

<context:annotation-config />
<context:component-scan base-package="com.example.package" />

<!-- Mail Service -->
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
    <property name="resourceLoaderPath" value="classpath:/mails" />
    <property name="preferFileSystemAccess" value="false" />
</bean>
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="smtp.mailgun.org" />
    <property name="username" value="[email protected]" />
    <property name="password" value="" />
    <property name="javaMailProperties">
        <props>
            <prop key="mail.smtp.auth">true</prop>
            <prop key="mail.smtp.starttls.enable">true</prop>
        </props>
    </property>
</bean>
<bean id="myMailSender" 
        class="com.example.package.service.MailService">
    <property name="mailSender" ref="mailSender" />
</bean>

As I mentioned above, the mailSender object is always nullin MailServiceclass.

正如我上面提到的,mailSender 对象总是nullMailService类中。

Maybe there's a conflict in mailSender object in MailSenderclass and MailServiceclass. The name of variables are the same, but they are different.

也许MailSender类和MailService类中的mailSender 对象存在冲突。变量的名称是相同的,但它们是不同的。

So I tried to rename the variables, but still not working.

所以我试图重命名变量,但仍然无法正常工作。

Unit Test Class:

单元测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:test-spring-context.xml"})
public class MailSenderTest {
    @Autowired
    @Qualifier("myMailSender")
    private MailSender mailSender;

    @Test
    public void test() {
        String templatePath = "/verifyEmail.vm";
        Map<String, Object> model = new HashMap<String, Object>();

        System.out.println(mailSender);

        String mailBody = mailSender.getMailContent(templatePath, model);
        System.out.println(mailBody);
    }
}

When I ran the test case, I got following exception:

当我运行测试用例时,出现以下异常:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.package.util.MailSender com.example.package.service.UserService.mailSender; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.package.util.MailSender] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=testzillaMailSender)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 54 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.package.util.MailSender] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=testzillaMailSender)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1308)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 56 more

Can you help me with it? Thx.

你能帮我解决吗?谢谢。

回答by sol4me

Your MailServiceclass is not being managed by spring. One way is to add annotation(Like @Service) to let spring handle it for you. E.g.

你的MailService班级不是由 spring 管理的。一种方法是添加注释(如@Service)让 spring 为您处理。例如

@Service
public class MailService {
    public void sendEmail(String email) {
        String templatePath = "/verifyEmail.vm";
        Map<String, Object> model = new HashMap<String, Object>();
        model.put("email", email);

        // mailSender is always null
        String mailBody = mailSender.getMailContent(templatePath, model);
    }

    // Autowired here is not working
    @Autowired
    private MailSender mailSender;
}

回答by LeoK

You need to add on the config xml <context:component-scan base-package="package.of.your.service"/>

您需要添加配置 xml <context:component-scan base-package="package.of.your.service"/>

in order spring pick this up.

为了春天拿起这个。

From what I can see on your configuration you have only <context:component-scan base-package="com.example.package" />. My guessing is that this is in a different package.

从我在您的配置中看到的情况来看,您只有<context:component-scan base-package="com.example.package" />. 我的猜测是这是在不同的包中。

回答by Steve

There are a couple of things wrong in there.

那里有一些问题。

You seem to be using an unfortunate mixture of XML and Java config. Your MailSenderhas been annotated as a @Component, so you don't need to have any XML to define it (assuming that your component scans are defined correctly).

您似乎正在使用 XML 和 Java 配置的不幸混合。您MailSender已被注释为@Component,因此您无需使用任何 XML 来定义它(假设您的组件扫描已正确定义)。

Also, it does not have a no-arg constructor, so the mechanism you're trying to use in the XML is not valid.

此外,它没有无参数构造函数,因此您尝试在 XML 中使用的机制无效。

Additionally in the classes which expect it to be autowired, they are putting the @Qualifier("myMailSender")annotation on the field. The MailSenderhas not been named, so there is no MailSenderwith that name. You can possibly just remove the @Qualifierannotation. However if you do need to ensure that it's a specific bean from a multitude of options, then you should name it in the @Controllerannotation like so:

此外,在期望它被自动装配的类中,他们将@Qualifier("myMailSender")注释放在字段上。在MailSender还没有被命名,所以没有MailSender使用该名称。您可以只删除@Qualifier注释。但是,如果您确实需要确保它是来自多个选项的特定 bean,那么您应该在@Controller注释中命名它,如下所示:

@Component("myMailSender")