注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。

手工装配依赖对象 

手工装配依赖对象,在这种方式中又有两种编程方式

  1. 在xml配置文件中,通过在bean节点下配置,上边博客已经讲解,再次不在缀余。
  1. 在java代码中使用@Autowired或@Resource注解方式进行装配。但我们需要在xml配置文件中配置以下信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<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-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
          <context:annotation-config/>
</beans>

PS:

1
<context:annotation-config/>

这个配置隐式注册了多个对注解进行解析处理的处理器:AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor

PS:之前我写过注解原理的博客,再此多说一句,注解本身和xml一样都是用于配置的,本身并不能干活,它之所以能干活,是因为它背后存在着处理器(也就是对应api)。

PS: 需要引入common-annotations.jar文件。

@Autowired和@Resource注解详解

在java代码中使用@Autowired或@Resource注解方式进行装配,这两个注解的区别是:@Autowired 默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。

1
2
3
4
5
6

    @Autowired 
private PersonDao  personDao;//用于字段上
@Autowired
public void setOrderDao(OrderDao orderDao) {//用于属性的setter方法上
this.orderDao = orderDao;
}

@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:

1
2

@Autowired  @Qualifier("personDaoBean")
private PersonDao  personDao;

@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。

1
2

@Resource(name=“personDaoBean”)
private PersonDao  personDao;//用于字段上

注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。

PS:@Resource在jdk中已经存在,不属于Spring,所以尽量使用这个注解。

编码剖析@Resource的原理:

自定义注解(模仿@Resource):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

package zmcSpring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.dom4j.Element;
/*
* 现在没法工作,只是一些配置信息
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface zmcResource {
public String name() default "";
}

PersonSevicebean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

package zmc;
import dao.PersonDao;
import zmcSpring.zmcResource;
import zmcjk.PersonService;
public class PersonServicebean implements PersonService {
  private String name;
  private PersonDao personDao ;
  public PersonServicebean(){
  
  }
  public PersonServicebean(String name, PersonDao personDao) {
super();
this.name = name;
this.personDao = personDao;
}
  public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public PersonDao getPersonDao() {
return personDao;
}
   @zmcResource
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
public void save(){
personDao.add();
}
}

自定义注解(zmcResource)处理器:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

package zmcSpring;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
/*
* 简单模拟Spring容器
*/
public class ZmcClassPathXMLApplicationContext {
    
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String,Object> sigletons = new HashMap<String,Object>();
public ZmcClassPathXMLApplicationContext(String fileName){
this.readXML(fileName);
this.instanceBeans();
this.annotationInject();
this.injectObject();//依赖注入
}
/*
* 暂且把zmcResouce处理器写在这里
*/
private void annotationInject() {
   for(String beanName: sigletons.keySet()){
   Object bean =sigletons.get(beanName);
   if(bean!=null){
  try{
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDescriptor properdesc : ps){
Method setter = properdesc.getWriteMethod();//获得属性的setter方法
Object obj = null;
if(setter!=null&&setter.isAnnotationPresent(zmcResource.class)){//判断是否存在zmcResource注解
zmcResource zmc = setter.getAnnotation(zmcResource.class);
if(zmc.name()!=null&&!"".equals(zmc.name())){
obj = sigletons.get(zmc.name());
}else{//没有设置name属性,即取得属性名称
obj = sigletons.get(properdesc.getName());
if(obj==null){//这时按类型
for(String beanname: sigletons.keySet()){
if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(beanname).getClass())){//两者类型是否匹配,前者类型是否是后者的父类或接口
obj=sigletons.get(beanname);
break;
}
}
}
}
setter.invoke(bean, obj);
}
}
Field[]  fileds = bean.getClass().getDeclaredFields();
for(Field field : fileds){
if(field.isAnnotationPresent(zmcResource.class)){
zmcResource zmc =field.getAnnotation(zmcResource.class);
Object obj = null;
if(zmc.name()!=null&&!"".equals(zmc.name())){
obj = sigletons.get(zmc.name());
}else{
obj = sigletons.get(field.getName());
if(obj==null){
for(String key : sigletons.keySet()){
if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){
obj  = sigletons.get(key);
break;
}
}
}
}
field.setAccessible(true);
field.set(bean, obj);
}
}
  }
  catch (Exception e){
  e.printStackTrace();
  }
   }
   }
}
/*
* 为bean属性注入值
*/
private void injectObject() {
for(BeanDefinition beanDefinition : beanDefines){
Object bean = sigletons.get(beanDefinition.getId());//此时bean还没有注入
//下面开始进行依赖注入
if(bean!=null){
//取得bean的属性描述
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();//bean的属性
for(PropertyDefinition propertyDefinition : beanDefinition.getProperty()){//用户配置文件中定义的属性
for(PropertyDescriptor properdesc : ps){
//判断配置文件中属性的名称和bean中属性的名称是否相同
if(propertyDefinition.getName().equals(properdesc.getName())){
Method setter = properdesc.getWriteMethod();
if(setter!=null){
if(propertyDefinition.getRef()!=null&&!"".equals(propertyDefinition.getRef().trim())){
Object value = sigletons.get(propertyDefinition.getRef());
try {
setter.invoke(bean, value);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//把引用对象注入到属性
}
}
}
}
}
} catch (IntrospectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*
* 完成bean的实例化
*/
private void instanceBeans(){
for(BeanDefinition beanDefinition : beanDefines){
try {
sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/*
* 读取XMl配置文件
* @param filename
*/
public void readXML(String fileName){
SAXReader saxReader = new SAXReader();
Document document = null;
try{
URL xmlpath = this.getClass().getClassLoader().getResource(fileName);
document = saxReader.read(xmlpath);
Map<String,String> nsMap = new HashMap<String,String>();
nsMap.put("ns", "http://www.springframework.org/schema/beans");//加入命名空间
XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
    xsub.setNamespaceURIs(nsMap);//设置命名空间
    List<Element> beans = xsub.selectNodes(document);
    for(Element element : beans){
       String id = element.attributeValue("id");
       String clazz = element.attributeValue("class");
       BeanDefinition beanDefinition = new BeanDefinition(id,clazz);
       
     XPath propertysub =  element.createXPath("ns:property");//nodename(节点名称):表示选择该节点的所有子节点
     propertysub.setNamespaceURIs(nsMap);
     List<Element> propertys = propertysub.selectNodes(element);
     for(Element property:propertys){
     String propertyName = property.attributeValue("name");
     String propertyRef = property.attributeValue("ref");
     String propertyValue = property.attributeValue("value");
     PropertyDefinition pd = new PropertyDefinition(propertyName, propertyRef,propertyValue);
     beanDefinition.getProperty().add(pd);
     }
     beanDefines.add(beanDefinition);
    }
}
catch (Exception e){
e.printStackTrace();
}
}
/*
* 获取bean实例
*/
public Object getBean(String beanName){
return this.sigletons.get(beanName);
}
}

转载于:https://www.cnblogs.com/zhangmingcheng/p/6548778.html

Spring第七弹—依赖注入之注解方式注入及编码解析@Resource原理相关推荐

  1. Spring依赖注入(注解方式)

    Spring依赖注入(注解方式) 在Spring中,尽管使用XML配置文件就可以实现Bean的装配工作,但如果应用中Bean的数量较多,会导致XML配置文件过于臃肿,从而给程序的维护与升级带来一定的困 ...

  2. spring的依赖注入 -------基于注解方式

    前言: 做了2年的软件,刚开始入行的时候,没有个目标基本上都是在摸索,技术看的我眼花缭乱,这个想学,那个也想学结果是对很多技术一知半解的,工作中才发现,我们要掌握的一门可以搞定快速开发搞定所有业务需求 ...

  3. Spring5——(一)spingIOC(入门介绍,spring创建bean,依赖,注入,注解方式)

    为什么要有框架? (1)对于web层来说,一个大型的程序往往需要编写大量的servlet,并且取值封装会非常繁琐. (2)对于dao层,要编写大量的sql语句,对于结果的解析也很麻烦,并且sql的复用 ...

  4. 2.3.1 spring属性注入-注解注入-半注解方式-前序

    注解注入自由度高,可以对部分类使用注解,也可以对所有类都使用注解. 下面代码是的Category使用xml定义java Bean, Product使用注解来定义java Bean 1.定义Catogo ...

  5. spring注解方式注入bean

    用注解的方式注入bean,spring的配置文件也要增加一些约束和导入注解所在的包 applicationContext.xml 1 <?xml version="1.0" ...

  6. Spring总结四:IOC和DI 注解方式

    首先我们要了解注解和xml配置的区别: 作用一样,但是注解写在Bean的上方来代替我们之前在xml文件中所做的bean配置,也就是说我们使用了注解的方式,就不用再xml里面进行配置了,相对来说注解方式 ...

  7. Spring源码之Bean的注册(注解方式)

    1.创建AnnotationConfigApplicationContext AnnotationConfigApplicationContext context = new AnnotationCo ...

  8. IDEA无法在service层用注解方式注入mapper

    现在项目集成了mybatis,在业务类service层中用@service  @Autowired 把mapper注入,实际运行时执行到该service报错,报mapper没有注入.(如果去掉@ser ...

  9. Spring(二)--------Spring配置、DI依赖注入、Bean自动装配

    Spring(二)--------Spring配置.DI依赖注入.Bean自动装配 5.Spring配置 5.1 别名 设置别名:第一种方式alias <!--其中name为ID的对应值--&g ...

最新文章

  1. 型人格 disc测试_3号,成就型人格的专业和职业选择@九型人格测试
  2. SQL Server 学习笔记
  3. [转]浅谈浏览器插件检测 和自定义协议的支持
  4. mysql二进制安装的优缺点_MYSQL的二进制安装
  5. REST服务的自动化测试
  6. C语言 main 函数 - C语言零基础入门教程
  7. 如何看待使用盗版windows系统的人?
  8. CodeBlocks常用操作快捷键
  9. 集成电路模拟版图入门-版图基础学习笔记(六)
  10. Laravel SQL查询中first、pluck、lists方法的使用
  11. Scala基础知识(个人总结)
  12. 高通MSM8909:LCD hx8394d驱动调试
  13. 基于PHP的图书管理系统
  14. 【已解决】笔记本电脑连接wifi异常(无法连接到这个网络)
  15. 智能电话机器人介绍(AI语音机器人)
  16. 孟郎诗词网3.0版本问题总结
  17. Chino with Equation
  18. 游戏平台系统云游戏实现
  19. Windows与网络基础23-传输介质-双绞线
  20. 玄铁RISC-V处理器软件生态

热门文章

  1. windows java配置_菜鸟教程 windows 配置java的环境变量
  2. textaligncenter仍然不居中_5个word你不知道的功能
  3. e-mobile帐号状态存在异常_企业微信添加好友提示”操作异常”怎么办?
  4. GNU C内嵌汇编学习笔记
  5. 个人收集的一些库、工具、技术介绍
  6. 初识openwrt(上)
  7. 【flink】Flink 使用IntelliJ IDEA 进行远程调试代码
  8. 【java】System.arraycopy为什么快
  9. 【Es】Es 集群设置分片很大导致集群无法选举主节点异常等
  10. 【MySQL】MySQL的帮助文档