Spring @Autowired 不工作
我在自动装配注释方面遇到一些问题。我的应用程序如下所示:
这是控制器:
@Controller
public class MyController {
@Autowired
@Qualifier("someService")
private SomeService someService;
....
}
它是一个服务层:
public interface SomeService {
...
}
@Service
public class SomeServiceImpl implements SomeService{
@Autowired
@Qualifier("myDAO")
private MyDAO myDAO;
....
}
DAO 层:
public interface MyDAO{
....
}
@Repository
public class JDBCDAOImpl implements MyDAO {
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
....
}
这是一个 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" />
所以...当我启动 Web 应用程序时,MyController 正确自动连线( someService 字段由 SomeServiceImpl 类对象正确注入),但 someService 的 myDAO 字段具有 null 值(未正确注入)。
你能帮我找出一个问题吗?
PS 这很有趣,但是当我将“bean id”从 myDAO 更改为另一个(例如 myDAO2)时,系统给我一个错误,注入无法完成,因为 bean myDAO 不存在。那么,Spring 进行了注入,但是它在哪里呢?为什么它不能正常工作?
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:
public interface MyDAO{
....
}
@Repository
public class JDBCDAOImpl implements MyDAO {
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
....
}
This is a app-service.xml file:
....
<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).
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我找到了解决方案。正如 Javi 所说(非常感谢你,Javi),我必须使用
@Repository
和@Service
注释来注释 DAO 和 Service 层类。现在我尝试这样写:并且
一切正常!
但我仍然没有找到这个问题的答案:如果应用程序会更复杂,并且会有更复杂的结构,其中
@Repositore
和@Service
注释不是首选一些类,如何正确注入位于较低级别的bean(在类的字段中,或在类的字段中的字段中)(当然使用@Autowire
注释)?I found the solution. As Javi said (thanks a lot for you, Javi), I have to annotate DAO and Service layer classes with
@Repository
and@Service
annotation. Now I've tried to write like this:and
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
@Repositore
and@Service
annotation 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@Autowire
annotation, of course)?我猜你需要
。I guess you need
<context:annotation-config />
.您可以使用
配置 .xml 文件中的条目。该条目将扫描/读取 java 类中所有指定的类型和注释。
You can use
entry in your configuration .xml file. This entry will scan/read all the stated type and annotations from the java classes.
要点:
定义为@Component注解的类,它必须有一个默认的构造函数。
现在,如果我们也将 @Component 应用于该类,那么它将始终使用 null 进行初始化。
因此,带有 @Autowired 的字段在其类定义中不应包含 @Component。
地址 bean 在学生类中自动装配。
让我们看看如果我们在 Address.java 中应用 @Component 会发生什么。
CollegeApp.java:
我们希望 Elgin 街能够自动连接学生地址。
Address.java:
Student.java:
Output: - Name:null Age:0 Address:null //此处未自动连接地址。
要解决此问题,只需按如下所示更改 Address.java:Address.java
:
输出:-
姓名:null 年龄:0 地址:Elgin street
Important points:
The class which is defined as a @Component annotation, it must have a default constructor.
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.
Address bean is autowired at Student class.
Let’s see what happens if we apply @Component at Address.java.
CollegeApp.java:
We want Elgin street to be autowired with Student address.
Address.java:
Student.java:
Output: - Name:null Age:0 Address:null //Address not Autowired here.
To resolve the issue, only change the Address.java as below:
Address.java:
Output:-
Name:null Age:0 Address:Elgin street
您应该在
spring-config.xml
中包含这部分 XML 代码:但您应该知道
与<; 之间的区别context:component-scan>
因为大多数人都建议这两个:1) 两个标签之间的第一个大区别是
用于激活应用程序上下文中已注册的 bean 中应用的注释。请注意,bean 是否通过哪种机制注册并不重要,例如使用
或它是在application-context.xml
文件本身中定义的。2) 第二个差异是由第一个差异本身驱动的。它确实在上下文中注册了 bean,并且还扫描了 bean 内的注释并激活它们。所以
;执行
的操作,但此外它还会扫描包并在应用程序上下文中注册 bean。You should include this section of XML code in
spring-config.xml
:but you should know the difference between
<context:annotation-config>
vs<context:component-scan>
as most people are suggesting these two :1) First big difference between 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 inapplication-context.xml
file itself.2) Second difference is 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.这可能有两个原因。
当您没有使用正确的 @Service/@Component/@Repository 注释来注释注入的对象或说服务时。
一旦您确定了第 1 点,接下来检查您的带注释的服务类的类包是否包含在主类中 Spring Boot 应用程序的类路径中。您可以使用以下注释进行配置。
这样做你告诉 spring 在类加载期间查看类的包。
There can be two reasons for this.
When you have not annotated the injected object or say service with proper @Service/@Component/@Repository annotations.
Once you have made sure of point 1 ,next check for whether the class package of your annotated service class is included in the class-path for your spring boot application in the main class.You can configure this using the following annotation.
Doing this you tell spring to look into the packages for the classes during class loading.
我的问题是,当我想要进行单元测试时,我在应用程序的入口点添加@ComponentScan,并在类中添加@Component来标记它,这样spring就可以在上下文中创建bean但仍然无法运行,最终我忘记用
这样的 方式注释测试类应该是
My problem is when i want to get unit test, i add @ComponentScan at entry point of Application and @Component for class to mark it so spring can create bean in context but still not run, eventually i forget to annotate the test class with
so it should be