spring通过注解方式依赖注入原理 (私有成员属性如何注入)

本文深入解析Spring框架如何通过反射机制创建对象及依赖注入,尤其针对私有成员属性的注入过程,揭示Spring创建对象的顺序与原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring通过注解方式依赖注入原理 (私有成员属性如何注入)

2018年05月23日 14:33:08

阅读数:416

一、spring如何创建依赖的对象

  用过spring的都知道我们在dao、service层加上@repository、@Service就能将这两个对象交给spring管理,在下次使用的时候使用@resource 或者@Autowired  就可以拿到而不需要自己再去new了,那么它是如何创建那些加上注解的对象的呢?

通过JAVA反射拿到无参构造函数

    以下只是举例:

Constructor<?> constructor = Teacher.class.getConstructor(null);

 可以看到class.getConstructor 可以拿到构造函数,然后再通过constructor.newInstance(null);实例化该对象,如此一来对象便创建好了,有参构造函数也是同理,区别是你要获得它的构造函数参数,然后在getConstructor 中传入参数的类型即可获取对应的构造函数了。

 

二、spring创建对象时如何注入依赖的对象 

现在我们知道spring创建对象是通过反射,那么如何该对象依赖其他对象时是如何操作的呢?举例:


 
  1. @Service

  2. public class Teacher {

  3.  
  4. @Resource

  5. private Student student;

  6.  
  7.  
  8.  
  9. public void print(){

  10. if(student!=null){

  11. System.out.println("student name:"+student.getName());

  12. }else{

  13. System.out.println("student is null");

  14. }

  15. }

  16. }

我们将Teacher对象交给spring管理了,但是需要在创建Teacher的同时将创建好的Student也赋值进去,可以看到Student对象是private私有的,而且没加get set,也就没法通过反射拿到get set方法并注入它的依赖对象了,这几天一直在查找相关资料终于弄明白了,其实还是反射。。。。。。

 

首先通过返回获取成员属性的注解,然后判断注解类型是根据对象类型还是名称注入,到这里都很好理解,关键在于私有对象如何注入,请看以下代码:


 
  1. Field[] fields = Teacher.class.getDeclaredFields();

  2. Student student = new Student();

  3. student.setName("zhangsan");

  4. Teacher teacher = new Teacher();

  5. for (Field field : fields) {

  6. if(field.getType().getName().equals(Student.class.getName())){

  7. //关键点!设置私有成员属性为可访问!

  8. field.setAccessible(true);

  9. //将已创建的对象赋值

  10. field.set(teacher, student);

  11. }

  12. }

  13. teacher.print();


我们假设Student 和Teacher对象都已经由spring创建好了,那么现在Teacher里有Student对象需要依赖注入,于是以上代码使我弄清楚了spring如果注入私有成员属性对象,其重点在于如何不通过get set方法把私有的成员对象赋值进去,关键代码:

field.setAccessible(true);

设置私有成员属性可以通过反射获取 ,然后通过

field.set(teacher, student);

奖Teacher对象里的成员属性student赋值进去,大功告成!具体的细节实现比如如何判断注解、如何保存SPRING创建的类等等相信大家不用看源码也知道大概是怎么做的了。

下面附上一段spring 装配对象的源码:


 
  1. /**

  2. * Either this or {@link #getResourceToInject} needs to be overridden.

  3. */

  4. protected void inject(Object target, String requestingBeanName, PropertyValues pvs) throws Throwable {

  5. if (this.isField) {

  6. Field field = (Field) this.member;

  7. ReflectionUtils.makeAccessible(field);

  8. field.set(target, getResourceToInject(target, requestingBeanName));

  9. }

  10. else {

  11. if (checkPropertySkipping(pvs)) {

  12. return;

  13. }

  14. try {

  15. Method method = (Method) this.member;

  16. ReflectionUtils.makeAccessible(method);

  17. method.invoke(target, getResourceToInject(target, requestingBeanName));

  18. }

  19. catch (InvocationTargetException ex) {

  20. throw ex.getTargetException();

  21. }

  22. }

  23. }

其中的

ReflectionUtils.makeAccessible(field);

正是设置私有成员属性可以通过反射访问!

 

spring创建对象的顺序

将对象交给spring管理也是就创建顺序的,那就是优先创建无任何依赖、有无参构造函数的对象,只有这样才能确保创建有依赖对象时可以将需要的成员对象注入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值