我继承了一些Java代码。几个类的实例变量是从/WEB-INF/servlet.properties中的属性值初始化的,如下所示:
@Value("${context.root}")
private String contextRoot;
当我在新类中尝试此操作时,实例变量未初始化。我的类的构造类似于有效的类,但它位于不同的包中(com.company.app.utilities与com.company.app.service)两者都导入相同的类:
import org.springframework.beans.factory.annotation.Value;
两者都有相应的公共getter和setter方法。
我已经查看了一些Spring文档和/WEB-INF/applicationContext.xml,但我没有看到任何需要配置的明显内容。
非常感谢任何帮助。
更新: 我在日志中看到以下条目:
[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时,在构造函数中捕获:
[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 Framework,而且让我有点困惑。当你说&#34;由Spring&#34;实例化时,这是否意味着将@Autowired放在使用我的新类的类中?我已经做了这个改变,并且我已经重写了我的类来实现一个接口,但现在Tomcat无法正常重启。代码,属性和日志如下:
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的类现在具有以下代码:
@Autowired
private S3Transfer s3Transfer;
/WEB-INF/applicationContext.xml和/WEB-INF/app-web-servlet.xml都在复杂的bean元素中包含以下元素:
<context:annotation-config />
<context:component-scan base-package="com.company.app" />
<context:property-placeholder location="/WEB-INF/servlet.properties" />
当我重新启动Tomcat时,初始化失败。以下是一些相关的日志条目:
[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美国东部时间: 显然,我的接口和类都需要@Service注释,因为Tomcat成功重启。这个注释的目的是什么?
答案 0 :(得分:0)
需要将新类的包(即com.company.app.service)添加到具有spring配置的xml文件中。 您需要将其添加到spring XML配置文件
<beans>
<context:component-scan base-package="com.package.containing.yourclass" />
</beans>
您需要这样,以便Spring了解扫描注释和/或创建bean所需的类。
答案 1 :(得分:-1)
请您分享您尝试访问变量的代码。如果它在contructor中,那么你将得到错误。由于在加载过程中被单独填充的单例bean将无法从属性配置器访问这些值。您可以考虑将代码移动到in-it方法,以便在访问字段时设置变量。 此外,确认您的班级是否由弹簧容器即时,而不是通过其他方式如新操作员