spring通过注解方式依赖注入原理 (私有成员属性如何注入)
一、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创建对象是通过反射,那么如何该对象依赖其他对象时是如何操作的呢?举例:
@Service
public class Teacher {
@Resource
private Student student; public void print(){
if(student!=null){
System.out.println("student name:"+student.getName());
}else{
System.out.println("student is null");
}
}
}
我们将Teacher对象交给spring管理了,但是需要在创建Teacher的同时将创建好的Student也赋值进去,可以看到Student对象是private私有的,而且没加get set,也就没法通过反射拿到get set方法并注入它的依赖对象了,这几天一直在查找相关资料终于弄明白了,其实还是反射。。。。。。
首先通过返回获取成员属性的注解,然后判断注解类型是根据对象类型还是名称注入,到这里都很好理解,关键在于私有对象如何注入,请看以下代码:
Field[] fields = Teacher.class.getDeclaredFields();
Student student = new Student();
student.setName("zhangsan");
Teacher teacher = new Teacher();
for (Field field : fields) {
if(field.getType().getName().equals(Student.class.getName())){
//关键点!设置私有成员属性为可访问!
field.setAccessible(true);
//将已创建的对象赋值
field.set(teacher, student);
}
}
teacher.print();
我们假设Student 和Teacher对象都已经由spring创建好了,那么现在Teacher里有Student对象需要依赖注入,于是以上代码使我弄清楚了spring如果注入私有成员属性对象,其重点在于如何不通过get set方法把私有的成员对象赋值进去,关键代码:
field.setAccessible(true);
设置私有成员属性可以通过反射获取 ,然后通过
field.set(teacher, student);
奖Teacher对象里的成员属性student赋值进去,大功告成!具体的细节实现比如如何判断注解、如何保存SPRING创建的类等等相信大家不用看源码也知道大概是怎么做的了。
下面附上一段spring 装配对象的源码:
/**
* Either this or {@link #getResourceToInject} needs to be overridden.
*/
protected void inject(Object target, String requestingBeanName, PropertyValues pvs) throws Throwable {
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
其中的
ReflectionUtils.makeAccessible(field);
正是设置私有成员属性可以通过反射访问!
spring创建对象的顺序
将对象交给spring管理也是就创建顺序的,那就是优先创建无任何依赖、有无参构造函数的对象,只有这样才能确保创建有依赖对象时可以将需要的成员对象注入。
spring通过注解方式依赖注入原理 (私有成员属性如何注入)的更多相关文章
- mybatis源码学习--spring+mybatis注解方式为什么mybatis的dao接口不需要实现类
相信大家在刚开始学习mybatis注解方式,或者spring+mybatis注解方式的时候,一定会有一个疑问,为什么mybatis的dao接口只需要一个接口,不需要实现类,就可以正常使用,笔者最开始的 ...
- (转)使用Spring的注解方式实现AOP的细节
http://blog.csdn.net/yerenyuan_pku/article/details/52879669 前面我们已经入门使用Spring的注解方式实现AOP了,现在我们再来学习使用Sp ...
- (转)使用Spring的注解方式实现AOP入门
http://blog.csdn.net/yerenyuan_pku/article/details/52865330 首先在Eclipse中新建一个普通的Java Project,名称为spring ...
- C++ //继承中的对象模型 //利用开发人员命令提示工具查看对象模型 //父类中所有非静态成员属性都会被 子类继承下去 //父类中私有成员属性 是被编译器给隐藏了 因此是访问不到 但是确实被继承下去了
1 //继承方式 2 //语法:class 子类 :继承方式 父类 3 //继承方式 三种: 4 //1.公共继承 5 //2.保护继承 6 //3.私有继承 7 8 /* 9 #include &l ...
- Spring使用注解方式注入多例的方式
目前Spring+Netty的开发方式这么火热,想把Netty注册成Spring组件就一定得用多例的方式,我不由得想吐槽明明这么常见的需求网上相关博客都少的很,这里给出Spring使用注解注入多例的方 ...
- spring IOC注解方式详解
本文分为三个部分:概述.使用注解进行属性注入.使用注解进行Bean的自动定义. 一,概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以 ...
- Spring的注解方式
在Java代码中可以使用@Resource或者@Autowired注解方式来经行注入.虽然@Resource和@Autowired都可以来完成注入依赖,但它们之间是有区别的. a.@Resource默 ...
- spring 纯注解方式 与AOP
spring注解方式 以前我也使用过纯注解方式.现在在这里做个记录 我们先认识几个我们都耳熟能详的注解 @configuration :从spring3.0这个注解就可以用于定义配置类,可以替换xml ...
- 转:Spring AOP 注解方式实现的一些“坑”
使用过Spring AOP的注解方式实现,也入过不少坑,现在做一下记录,希望有同样需求的朋友可以少走弯路 使用之前还是先过一下官方文档吧,至少可以少走弯路,不用担心英文读不懂,其实只看代码例子就能理解 ...
随机推荐
- 关于 Mesos,你知道多少?13 个问题带你深入了解 Mesos
听过不少人在讨论 Mesos,然而并不是很明白 Mesos 到底能够解决什么问题,使用场景是怎样的,周伟涛(国内较早一批接触使用 Docker,Mesos 等技术的开发者)用一句话形容它, Mesos ...
- git安装使用详解
Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不 需要联网了,因为版本都是在自己的电脑上.既然每个人的电脑都有一个完整的版本库,那多个人如何 ...
- Matlab使用鼠标标注图像位置并返回坐标(标注图像ROI)
代码 function ROI=LabelBox(filename) Mat=imread(filename); imshow(Mat); mouse=imrect; pos=getPosition( ...
- 用WPF窗体打造个性化界面的图片浏览器
原文:用WPF窗体打造个性化界面的图片浏览器 本文使用WPF窗体(XAML及C#)与Win Form控件(FolderBrowserDialog)结合的方式, 演示制作了一个简易漂亮的WPF图片浏览器 ...
- wpf无边框窗体移动和大小调整
原文:wpf无边框窗体移动和大小调整 using System; using System.Windows; using System.Windows.Interop; namespace Wpf ...
- Node.js && Angular && TypeScript 环境安装与更新
安装 Node.js 下载并安装Node.js Angular 执行命令 npm install -g @angular/cli 参考资料: angular quickstart TypeScript ...
- MIS的趋势必定是围绕机器取代人手,分工越来越细(小餐厅都支持微信自助点餐,结账时就打个折,相当于省了1、2个人手,SQL发明以后,程序员的工作更多了)
最后,我还想简略的谈谈MIS及MIS快速开发工具的未来. MIS的趋势必定是围绕机器取代人手,分工越来越细.比如:现在有些小型的咖啡厅里的财务子系统就简单到不需要使用者有会计知识,相当于省了会计人手: ...
- MyBatis 模板
mybatis-config.xml: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE co ...
- How do I duplicate a resource reference in code behind in WPF?如何在WPF后台代码中中复制引用的资源?
原文 https://stackoverflow.com/questions/28240528/how-do-i-duplicate-a-resource-reference-in-code-behi ...
- Django 创建超级管理员失败
django.db.utils.DataError: (1406, "Data too long for column 'gender' at row 1") 解决方案 在执行mi ...