Spring第七弹—依赖注入之注解方式注入及编码解析@Resource原理
注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。
手工装配依赖对象
手工装配依赖对象,在这种方式中又有两种编程方式
- 在xml配置文件中,通过在bean节点下配置,上边博客已经讲解,再次不在缀余。
- 在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);
}
}
|
Spring第七弹—依赖注入之注解方式注入及编码解析@Resource原理的更多相关文章
- EJB通过注解方式注入并使用其他EJB或者服务、配置JBoss数据源
通过注解方式注入并使用其他EJB或者服务 真实项目EJB对象很多,EJB之间也可以互相调用, 在项目HelloWorld下新建接口Other在cn.hqu.ejb3下: public interfac ...
- Spring声明式事务管理(基于注解方式实现)
----------------------siwuxie095 Spring 声明式事务管理(基于注解方式实现) 以转 ...
- EJB通过注解方式注入并使用其它EJB或者服务、配置JBoss数据源
版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/Jerome_s/article/details/37103171 通过注解方式注入并使用其他EJB或者服务 ...
- Spring第六弹—-依赖注入之使用构造器注入与使用属性setter方法注入
所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中. 使用构造器注入 1 2 3 4 <constructor-arg index=“0” type=“java.lang. ...
- Spring 依赖注入控制反转实现,及编码解析(自制容器)
定义: 在运行期,由外部容器动态的将依赖对象动态地注入到组件中. 两种方式: 手工装配 -set方式 -构造器 -注解方式 自动装配(不推荐) 1利用构造器 2set方法注入 dao: package ...
- spring注解方式注入
1.通过Resource注入 1.在属性上注入 1.默认注入 即不指定spring容器里面的名字 匹配规则:先通过属性的名字查找 再通过属性类型与实现类类型匹配查找 当有两个实现类会报错 2.通过指定 ...
- spring注解方式注入bean
用注解的方式注入bean,spring的配置文件也要增加一些约束和导入注解所在的包 applicationContext.xml <?xml version="1.0" en ...
- 【初识Spring】对象(Bean)实例化及属性注入(注解方式)
通过xml的方式进行对象的实列化或属性注入或许有一些繁琐,所以在开发中常用的方式更多是通过注解的方式实现对象实例化和属性注入的. 开始之前 1.导入相关的包(除了导入基本的包还要导入aop的包): 创 ...
- Spring总结四:IOC和DI 注解方式
首先我们要了解注解和xml配置的区别: 作用一样,但是注解写在Bean的上方来代替我们之前在xml文件中所做的bean配置,也就是说我们使用了注解的方式,就不用再xml里面进行配置了,相对来说注解方式 ...
随机推荐
- hdu 1233:还是畅通工程(数据结构,图,最小生成树,普里姆(Prim)算法)
还是畅通工程 Time Limit : 4000/2000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submis ...
- hdu 1086:You can Solve a Geometry Problem too(计算几何,判断两线段相交,水题)
You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/3 ...
- 标签中的rel属性的含义
rel与rev属性相同,它们都是属于LinkTypes属性. rel 属性 -- rel属性,描述了当前页面与href所指定文档的关系, rel是relationship(关系)的英文缩写. rev ...
- 【BZOJ4244】邮戳拉力赛 DP
[BZOJ4244]邮戳拉力赛 Description IOI铁路是由N+2个站点构成的直线线路.这条线路的车站从某一端的车站开始顺次标号为0...N+1. 这条路线上行驶的电车分为上行电车和下行电车 ...
- 【BZOJ2253】[2010 Beijing wc]纸箱堆叠 cdq分治
[BZOJ2253][2010 Beijing wc]纸箱堆叠 Description P 工厂是一个生产纸箱的工厂.纸箱生产线在人工输入三个参数 n p a , , 之后,即可自动化生产三边边长为 ...
- spring的@Transactional注解详细用法(转载)
概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性.Spring Framework对事务管理提供了一致的抽象,其特点如下: 为不同的事务API提供一致的编程模型, ...
- angularJs-脏检查
来自:http://www.cnblogs.com/liuyanan/p/4935652.html scope是一个指向应用model的object,也是表达式的执行上下文. scope被放置在一个类 ...
- WARNING:tensorflow:From /usr/lib/python2.7/site-packages/tensorflow/python/util/tf_should_use.py:189: initialize_all_variables (from tensorflow.python.ops.variables) is deprecated and will be removed
initialize_all_variables已被弃用,将在2017-03-02之后删除. 说明更新:使用tf.global_variables_initializer代替. 就把tf.initia ...
- WHICH ONE IS BETTER FOR NEWBIE?
DROP PROCEDURE IF EXISTS w_array; DELIMITER /w/ )) BEGIN ) DO SET @w = LOCATE(',', w_arr); ); SET @w ...
- Tilera--100核cpu
市场对多核的需求越来越多,主要是因为单核处理能力不可能像以往那样不断地提升.从上世纪90 年代开始,整个产业遵循摩尔定律,即芯片上可容纳的晶体管数目每隔18个月便会增加一倍,性能也提升一倍.随着时间的 ...