首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring annotation @Value -我遗漏了什么?

Spring annotation @Value -我遗漏了什么?
EN

Stack Overflow用户
提问于 2014-12-03 05:03:06
回答 2查看 1.9K关注 0票数 0

我继承了一些Java代码。有几个类的实例变量是从/WEB-INF/servlet.properties中的属性值初始化的,如下所示:

代码语言:javascript
复制
@Value("${context.root}")
private String contextRoot;

当我在一个新的类中尝试这样做时,实例变量没有初始化。我的类的构造与正常工作的类相似,但它位于不同的包中(com.company.app.utilities与com.company.app.service)两者都导入相同的类:

代码语言:javascript
复制
import org.springframework.beans.factory.annotation.Value;

两者都有相应的公共getter和setter方法。

我已经查看了一些Spring文档和/WEB-INF/applicationContext.xml,但我没有看到任何明显的需要配置的内容。

任何帮助都是非常感谢的。

更新:我在日志中看到以下条目:

代码语言:javascript
复制
[localhost-startStop-1] 03 Dec 2014 02:47:10,791 INFO : org.springframework.context.support.PropertySourcesPlaceholderConfigurer - Loading properties file from ServletContext resource [/WEB-INF/servlet.properties]
[localhost-startStop-1] 03 Dec 2014 02:47:10,938 INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@601e8f7d: defining beans [...,contactServiceImpl,s3Transfer,...]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@32f5f812

我省略了日志条目中的所有其他单例,以强调原始类和我的类都在列表中;但是,我创建了一个构造函数,而原始类没有构造函数。日志中的下一行是我在getter方法中抛出的异常,当值为null时,在构造函数中捕获:

代码语言:javascript
复制
[localhost-startStop-1] 03 Dec 2014 02:47:12,730 ERROR: com.company.app.utilities.S3Transfer - bucketName is null!
java.lang.Exception: bucketName is null!
    at com.company.app.utilities.S3Transfer.getBucketName(S3Transfer.java:129)
    at com.company.app.utilities.S3Transfer.<init>(S3Transfer.java:48)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1000)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:953)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:651)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:599)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:665)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:518)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:459)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
    at javax.servlet.GenericServlet.init(GenericServlet.java:160)

..。

我应该移除构造器吗?如果是这样,是否有额外的Spring配置来实例化这个类的单例?谢谢。

更新2014-12-03:我想我离开Java太久了,因为我上一次编写AOP时,还没有Spring框架,这让我有点困惑。当您说“由Spring实例化”时,这是否意味着在使用我的新类的类中放置@Autowired?我已经做了此更改,并重写了我的类以实现接口,但现在Tomcat无法正确重新启动。代码、属性和日志如下:

代码语言:javascript
复制
package com.company.app.utilities;

import com.company.app.bean.Contact;
import java.io.InputStream;

public interface S3Transfer {
    String storeContactProfilePicture(Long idUser, Contact contact);
    String storeContactProfilePicture(Long idUser, Long idContact, InputStream inStream);
    String storeUserProfilePicture(Long idUser, String fileName, String accountType);
}

package com.company.app.utilities;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.company.app.bean.Contact;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;

public class S3TransferImpl implements S3Transfer {

    private final AmazonS3 s3client = new AmazonS3Client();

    private final Logger logger = Logger.getLogger(getClass());

    @Value("${context.root}")
    private String contextRoot;

    @Value("${s3.bucket.name}")
    private String bucketName;

    @Value("${contact.profile.picture}")
    private String contactProfilePictureKey;

    @Value("${user.profile.picture}")
    private String userPictureKey;

    public String storeContactProfilePicture(Long idUser, Contact contact) {
    String keyName = getContactProfilePictureKey().replaceAll("<<idUsr>>", idUser.toString()).replaceAll("<<idContact>>", contact.getIdContact().toString());
    String fileName = contact.getPicture();

    storeObjectFromFileName(fileName, keyName);
    return contextRoot + keyName;
    }

    public String storeContactProfilePicture(Long idUser, Long idContact, InputStream inStream) {
    String keyName = getContactProfilePictureKey().replaceAll("<<idUsr>>", idUser.toString()).replaceAll("<<idContact>>", idContact.toString());

    storeObject(inStream, keyName);
    return contextRoot + keyName;
    }

    public String storeUserProfilePicture(Long idUser, String fileName, String accountType) {
    String keyName = getUserPictureKey().replaceAll("<<idUsr>>", idUser.toString()).replace("<<socialNetwork>>", accountType);

    storeObjectFromFileName(fileName, keyName);
    return contextRoot + keyName;
    }

    private void storeObjectFromFileName(String fileName, String keyName) {
    try {
        logger.info("Uploading " + fileName + " to " + keyName);
        InputStream inStream = new URL(fileName).openStream();
        storeObject(inStream, keyName);
    } catch (IOException e) {
        logger.error(e.getMessage(), e);
    }
    }

    private void storeObject(InputStream inStream, String keyName) {
    try {
        this.s3client.putObject(new PutObjectRequest(getBucketName(), keyName, inStream, null));
    } catch (AmazonServiceException ase) {
        logger.error("Caught an AmazonServiceException, which "
            + "means your request made it "
            + "to Amazon S3, but was rejected with an error response"
            + " for some reason.");
        logger.error("Error Message:    " + ase.getMessage());
        logger.error("HTTP Status Code: " + ase.getStatusCode());
        logger.error("AWS Error Code:   " + ase.getErrorCode());
        logger.error("Error Type:       " + ase.getErrorType());
        logger.error("Request ID:       " + ase.getRequestId());
    } catch (AmazonClientException ace) {
        logger.error("Caught an AmazonClientException, which "
            + "means the client encountered "
            + "an internal error while trying to "
            + "communicate with S3, "
            + "such as not being able to access the network.");
        logger.error("Error Message: " + ace.getMessage());
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
    }

    public String getContextRoot() {
    return contextRoot;
    }

    public void setContextRoot(String contextRoot) {
    this.contextRoot = contextRoot;
    }

    public String getBucketName() {
    return bucketName;
    }

    public void setBucketName(String bucketName) {
    this.bucketName = bucketName;
    }

    private String getContactProfilePictureKey() {
    return contactProfilePictureKey;
    }

    private void setContactProfilePictureKey(String contactProfilePictureKey) {
    this.contactProfilePictureKey = contactProfilePictureKey;
    }

    private String getUserPictureKey() {
    return userPictureKey;
    }

    private void setUserPictureKey(String userPictureKey) {
    this.userPictureKey = userPictureKey;
    }

}

使用S3Transfer的类现在具有以下代码:

代码语言:javascript
复制
@Autowired
private S3Transfer s3Transfer;

/WEB-INF/applicationContext.xml和/WEB-INF/app-web-servlet.xml在复杂的bean元素中都有以下元素:

代码语言:javascript
复制
<context:annotation-config />
<context:component-scan base-package="com.company.app" />
<context:property-placeholder location="/WEB-INF/servlet.properties" />

当我重新启动Tomcat时,初始化失败。以下是一些相关的日志条目:

代码语言:javascript
复制
    [localhost-startStop-1] 03 Dec 2014 18:39:03,407 INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/applicationContext.xml]
[localhost-startStop-1] 03 Dec 2014 18:39:03,926 INFO : org.springframework.context.annotation.ClassPathBeanDefinitionScanner - JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
[localhost-startStop-1] 03 Dec 2014 18:39:05,990 INFO : org.springframework.context.annotation.ClassPathBeanDefinitionScanner - JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
[localhost-startStop-1] 03 Dec 2014 18:39:07,983 INFO : org.springframework.context.support.PropertySourcesPlaceholderConfigurer - Loading properties file from ServletContext resource [/WEB-INF/servlet.properties]
[localhost-startStop-1] 03 Dec 2014 18:39:08,708 INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@63655d7a: defining beans [... {long list, but s3TransferImpl is not in the list} ...]; root of factory hierarchy
[localhost-startStop-1] 03 Dec 2014 18:39:10,667 INFO : org.springframework.jdbc.datasource.DriverManagerDataSource - Loaded JDBC driver: com.mysql.jdbc.Driver
[localhost-startStop-1] 03 Dec 2014 18:39:20,152 ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#0' while setting bean property 'sourceList' with key [0]; nested exception is ... {long list of nested exceptions}...; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.company.app.utilities.S3Transfer] 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)}
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)

更新2014-12-03 14:50 EST:显然,我的接口和类都需要@Service注释,因为Tomcat成功重启。这个注解的目的是什么?

EN

回答 2

Stack Overflow用户

发布于 2014-12-03 05:08:59

需要将新类com.company.app.service的包添加到具有spring配置的xml文件中。您需要将此代码添加到spring XML配置文件中。

代码语言:javascript
复制
<beans>
    <context:component-scan base-package="com.package.containing.yourclass" />
</beans>

您需要这样做,以便Spring了解它需要扫描哪些类来查找注释和/或创建bean。

票数 0
EN

Stack Overflow用户

发布于 2014-12-03 12:22:56

你能分享一下你试图访问变量的代码吗?如果它在构造器内部,那么你会得到错误。因为在加载过程中被激发的单例bean将不能从属性配置器访问这些值。您可以考虑将代码移到in-it方法中,以便在访问字段时设置变量。另外,确认您的类是否由spring容器实例化,而不是通过new运算符等其他方式实例化。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27258908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档