Spring中注解@Autowired与@Resource的依赖注入源码分析

   上篇文章Spring中Xml配置Bean的依赖注入源码分析,讲的是通过XML方式配置Bean来实现依赖注入的,主要是通过BeanWrapperImpl.setPropertyValue方法,调用java类提供的Setter方法,利用反射机制注入属性值,完成依赖注入。

     这次讲讲注解@Autowired与@Resource,是如何实现依赖注入的。

     1.@Autowired实现依赖注入

测试Main代码:

public class BeanExample {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        StudentService studentService = (StudentService) applicationContext.getBean("studentServiceImpl");
        studentService.hello();
    }
}

开启注解:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.hand"/>
</beans>

java类:

@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private UserService userService;

    @Override
    public void hello() {
        userService.hello("haha");
    }
}

因为开启了注解注入,在Spring容器启动时,默认会向BeanFactory注册AutowiredAnnotationBeanPostProcessor后置处理器,也就是在Bean实例化完后,用来做依赖注入工作的。

  


AutowiredAnnotationBeanPostProcessor处理器就是用来实现@Autowired的依赖注入的。









到这里,就完成了@AutoWired方式的属性注入了。

PS:常见注入异常报错代码位置。



     2.@Resource实现依赖注入

        测试代码同上,就是注入类型@AutoWired改为@Resource。

        

       @Resource类型注解,依赖注入的处理类是CommonAnnotationBeanPostProcessor

        



到这里,就完成了@Resource方式的属性的依赖注入。

这里不够准确,上面是先按名称找。autowireResouce可能按类型也可能按名称,就看你有么有给@Resource加name属性了。

下面我会上个案例。

     




给@Resource指定name值。


   



      3.注解+Setter混合注入(当然正常情况,不会这么用 )

        

public class BeanExample {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        StudentService studentService = (StudentService) applicationContext.getBean("studentServiceImpl");
        studentService.hello();
    }
}
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.hand"/> <!--开启注解-->
    <bean id="studentServiceImpl" class="com.hand.user.dal.StudentServiceImpl">
        <!--该属性通过属性注入,userService通过注解注入-->
        <property name="teacherService" ref="teacherService"></property>
    </bean>
</beans>
/**
 * Function Desc: 注解+Setter混合注入。
 * Date:2018/3/31 16:15
 * author:[email protected]
 */
public class StudentServiceImpl implements StudentService {
    @Resource
    private UserService userService;//通过注解注入

    private TeacherService teacherService;//通过Setter注入

    public void setTeacherService(TeacherService teacherService) {
        this.teacherService = teacherService;
    }

    @Override
    public void hello() {
        userService.hello("haha");
    }
}




可以看出,Spring底层代码每个方法职责单一,结构合理。

主要流程:解析bean-》保存beanDefition到IOC容器-》根据beanDefition实例化-》根据BeanpostProcessor依赖注入


总结:

1.Autowired是Spring提供的,Resouce是JDK提供的。

2.Autowired通过AutowiredAnnotationBeanPostProcessor实现属性的依赖注入,Resouce通过CommonAnnotationBeanPostProcessor。实现属性的依赖注入。

3.注解方式实例化的bean,默认都是单例,没找到定义bean Scope的入口。

4.Autowired注解严格来说,只是按类型来注入的。因为如果按类型找不到依赖的bean,直接抛异常了。配置了多个类型的bean时,会返回指定@Primary注解的bean。

5.Resouce注解,当么有指定name时,是按类型注入的;指定了name,才按name。当然前提时,我还没弄明白jndiFactory是怎么样用的。

猜你喜欢

转载自blog.csdn.net/bawcwchen/article/details/79793288