Spring中的@Autowired和@Resource都可以用来装配Bean,实现注释型的IOC(可以用在类的成员变量,构造函数或方法上),但两者却有一些区别:
1,@Autowired是Spring中的(import org.springframework.beans.factory.annotation.Autowired),而@Resource是Javax中的(import javax.annotation.Resource)
2,@Autowired按byType自动注入,而@Resource默认按 byName自动注入
可以参考: http://developer.51cto.com/art/201104/255395.htm
可以看一个实际的问题:
代码中的注释装配
@Service
public class MailNotifServiceImpl extends AbstractThreadPool<MailNotifTask> implements MailNotifService {
@Autowired
private JavaMailSender mailSender;
xml文件中的配置
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.163.com"/>
运行异常描述
2012-11-27 20:21:44 org.apache.catalina.core.StandardContext listenerStart
严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListenerorg.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mailNotifServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bubinglv.util.msgqueue.MessageSender com.bubinglv.notification.email.MailNotifServiceImpl.msgSender; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageSender': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected org.springframework.amqp.core.Binding com.bubinglv.util.msgqueue.MessageSender.binding; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mailBinding' defined in ServletContext resource [/WEB-INF/spring/util/util-context.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.lang.String]: Could not convert constructor argument value of type [org.springframework.amqp.core.Queue] to required type [java.lang.String]: Failed to convert value of type 'org.springframework.amqp.core.Queue' to required type 'java.lang.String'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.amqp.core.Queue] to required type [java.lang.String]: no matching editors or conversion strategy found
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
问题原因:
因为@Autowired是按照Type方式进行依赖注入,而该例子中JavaMailSender是一个接口,并不是具体的实现类,所以Spring容器也不知道该用哪个实现类来注入,抛出异常
解决方法:以下三种方式均可以解决上面问题
1,将@Autowired换成@Resource,即
@Resource
private JavaMailSender mailSender;
2,将属性类型换成具体的实现类(虽然能解决问题,但失去了Ioc的灵活性),即
@Autowired
private JavaMailSenderImpl mailSender;
3,使用@Autowired和@Qualifier的结合
@Autowired
@Qualifier("mailSender")
private JavaMailSender mailSender;
故还是建议使用@Resource,补充一下@Resource装配的顺序
a.如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
b.如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
c.如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
d.如果既没有指定name,又没有指定type,则自动按照byName方式进行装配(见2);如果没有匹配,则回退为一个原始类型(UserDao)进行匹配,如果匹配则自动装配;