Spring @Autowired 不工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4287837/
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
Spring @Autowired not working
提问by Ilnur
I have some problems wth autowire annotation. My app looks like this:
我在自动装配注释方面遇到了一些问题。我的应用程序如下所示:
Here is controller:
这是控制器:
@Controller
public class MyController {
@Autowired
@Qualifier("someService")
private SomeService someService;
....
}
It's a service layer:
这是一个服务层:
public interface SomeService {
...
}
@Service
public class SomeServiceImpl implements SomeService{
@Autowired
@Qualifier("myDAO")
private MyDAO myDAO;
....
}
And DAO layer:
和 DAO 层:
public interface MyDAO{
....
}
@Repository
public class JDBCDAOImpl implements MyDAO {
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
....
}
This is a app-service.xml file:
这是一个 app-service.xml 文件:
....
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<bean id="SomeService" class="com.service.SomeServiceImpl" />
<bean id="myDAO" class="com.db.JDBCDAOImpl" />
So... When I'm launching a web-app, MyController Autowires correctly (the someService field correctly injected by SomeServiceImpl class object), but myDAO feild of someService has null value (not injected properly).
所以......当我启动一个 web 应用程序时,MyController 自动装配正确(SomeServiceImpl 类对象正确注入了 someService 字段),但是 someService 的 myDAO 字段具有空值(未正确注入)。
Could you help me to find a problem?
你能帮我找出问题吗?
P.S. Its interesting, but when I'm changing a "bean id" from myDAO to some another (e.g. myDAO2), system gives me an error, that injecting could not be done, because bean myDAO doesn't exist. So, Spring make an injection, but where it is? And why it's not work correctly?
PS 这很有趣,但是当我将“bean id”从 myDAO 更改为另一个(例如 myDAO2)时,系统给了我一个错误,无法完成注入,因为 bean myDAO 不存在。那么,Spring 进行了注入,但它在哪里呢?为什么它不能正常工作?
回答by Ilnur
I found the solution. As Javi said (thanks a lot for you, Javi), I have to annotate DAO and Service layer classes with @Repositoryand @Serviceannotation. Now I've tried to write like this:
我找到了解决方案。正如 Javi 所说(非常感谢你,Javi),我必须用@Repository和@Service注释来注释 DAO 和服务层类。现在我试着这样写:
@Service("someService")
public class SomeServiceImpl implements SomeService{
@Autowired
@Qualifier("myDAO")
private MyDAO myDAO;
....
}
and
和
@Repository("myDAO")
public class JDBCDAOImpl implements MyDAO {
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
....
}
and all works fine!!!
一切正常!!!
But I still not found an answer for this quesion: if application will be more complex, and will have more complex structure, where @Repositoreand @Serviceannotation are not preferred for some classes, how to inject correctly beans, which located in lower levels (in a fields of classes, or in a field of fields of classes) (with @Autowireannotation, of course)?
但是我仍然没有找到这个问题的答案:如果应用程序将更复杂,并且将具有更复杂的结构,某些类不首选where@Repositore和@Serviceannotation,如何正确注入位于较低级别(在字段中)的 bean类,或在类字段的字段中)(@Autowire当然有注释)?
回答by axtavt
I guess you need <context:annotation-config />.
我猜你需要<context:annotation-config />。
回答by Krishna Kumar Chourasiya
You can use
您可以使用
<context:component-scan base-package="PATH OF THE BASE PACKAGE"/>
entry in your configuration .xml file. This entry will scan/read all the stated type and annotations from the java classes.
配置 .xml 文件中的条目。此条目将扫描/读取 java 类中所有声明的类型和注释。
回答by Sumit Basu
Important points:
要点:
- Sometimes, @Component may leads to a problem where it might say no default constructor found. The class which is defined as a @Component annotation, it must have a default constructor.
- Suppose, we have applied @Autowired annotation at field which is a user defined class reference. Now, if we also apply @Component to that class then it will always be initialized with null. So, a field with @Autowired should not have @Component at its class definition.
- By default @Autowired is byType.
- 有时,@Component 可能会导致一个问题,它可能会说没有找到默认构造函数。定义为@Component 注解的类,它必须有一个默认构造函数。
- 假设,我们在字段上应用了 @Autowired 注释,这是一个用户定义的类引用。现在,如果我们也将 @Component 应用于该类,那么它将始终使用 null 进行初始化。因此,带有 @Autowired 的字段不应在其类定义中包含 @Component。
- 默认情况下@Autowired 是 byType。
Address bean is autowired at Student class. Let's see what happens if we apply @Component at Address.java.
地址 bean 在 Student 类中自动装配。让我们看看如果我们在 Address.java 中应用 @Component 会发生什么。
CollegeApp.java:
CollegeApp.java:
package com.myTest
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.bean.Address;
import com.bean.Student;
//Component scanning will for only those classes
//which is defined as @Component. But, all the class should not use
//@Component always even if the class is enabled with auto
//component scanning, specially the class which is Autowired
//Or which is a property of another class
@Configuration
@ComponentScan(basePackages={"com.bean"})
public class CollegeApp {
@Bean
public Address getAddress(){
return new Address("Elgin street");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
We want Elgin street to be autowired with Student address.
我们希望 Elgin street 自动连接学生地址。
Address.java:
地址.java:
package com.bean;
import org.springframework.stereotype.Component;
@Component
public class Address {
private String street;
public Address()
{
}
public Address(String theStreet)
{
street=theStreet;
}
public String toString()
{
return (" Address:"+street);
}
}
Student.java:
学生.java:
package com.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Student {
private String name;
private int age;
private Address address;
public Student()
{
}
public Student(String theName,int theAge)
{
name=theName;age=theAge;
}
@Autowired
public void setAddress(Address address) {
this.address = address;
}
public String toString()
{
return ("Name:"+name+" Age:"+age+ " "+address);
}
}
Output: - Name:null Age:0 Address:null //Address not Autowired here.
输出: - Name:null Age:0 Address:null //此处未自动连线的地址。
To resolve the issue, only change the Address.java as below:
要解决此问题,只需更改 Address.java 如下:
Address.java:
地址.java:
package com.bean;
public class Address {
private String street;
public Address(String theStreet)
{
street=theStreet;
}
public String toString()
{
return (" Address:"+street);
}
}
Output:- Name:null Age:0 Address:Elgin street
输出:- 姓名:空 年龄:0 地址:埃尔金街
回答by shubham srivastava
You should include this section of XML code in spring-config.xml:
您应该将这部分 XML 代码包含在spring-config.xml:
<context:component-scan base-package="Fully.Qualified.Package.Name" />
but you should know the difference between <context:annotation-config>vs <context:component-scan>as most people are suggesting these two :
但是您应该知道<context:annotation-config>vs之间的区别,<context:component-scan>因为大多数人都建议这两个:
1) First big differencebetween both tags is that <context:annotation-config>is used to activate applied annotations in already registered beans in application context. Note that it simply does not matter whether bean was registered by which mechanism e.g. using <context:component-scan>or it was defined in application-context.xmlfile itself.
1)两个标签之间的第一个大区别<context:annotation-config>是用于激活应用程序上下文中已注册bean中的应用注释。请注意,bean 是通过哪种机制注册的,例如 using<context:component-scan>还是在application-context.xml文件本身中定义的,这根本无关紧要。
2) Second differenceis driven from first difference itself. It does register the beans in context + it also scans the annotations inside beans and activate them. So <context:component-scan>; does what <context:annotation-config>does, but additionally it scan the packages and register the beans in application context.
2)二阶差分是由一阶差分本身驱动的。它确实在上下文中注册 bean + 它还扫描 bean 中的注释并激活它们。所以<context:component-scan>; 做了什么<context:annotation-config>,但另外它扫描包并在应用程序上下文中注册bean。
回答by sashicon
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Specifying base package of the Components like Controller, Service,
DAO -->
<context:component-scan base-package="com.jwt" />
<!-- Getting Database properties -->
<context:property-placeholder location="classpath:application.properties" />
<!-- DataSource -->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="${database.driver}"></property>
<property name="url" value="${database.url}"></property>
<property name="username" value="${database.user}"></property>
<property name="password" value="${database.password}"></property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
</beans>

