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

手工装配依赖对象 

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

  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);
}
}

Spring第七弹—依赖注入之注解方式注入及编码解析@Resource原理的更多相关文章

  1. EJB通过注解方式注入并使用其他EJB或者服务、配置JBoss数据源

    通过注解方式注入并使用其他EJB或者服务 真实项目EJB对象很多,EJB之间也可以互相调用, 在项目HelloWorld下新建接口Other在cn.hqu.ejb3下: public interfac ...

  2. Spring声明式事务管理(基于注解方式实现)

    ----------------------siwuxie095                                 Spring 声明式事务管理(基于注解方式实现)         以转 ...

  3. EJB通过注解方式注入并使用其它EJB或者服务、配置JBoss数据源

    版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/Jerome_s/article/details/37103171 通过注解方式注入并使用其他EJB或者服务 ...

  4. Spring第六弹—-依赖注入之使用构造器注入与使用属性setter方法注入

    所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中. 使用构造器注入   1 2 3 4 <constructor-arg index=“0” type=“java.lang. ...

  5. Spring 依赖注入控制反转实现,及编码解析(自制容器)

    定义: 在运行期,由外部容器动态的将依赖对象动态地注入到组件中. 两种方式: 手工装配 -set方式 -构造器 -注解方式 自动装配(不推荐) 1利用构造器 2set方法注入 dao: package ...

  6. spring注解方式注入

    1.通过Resource注入 1.在属性上注入 1.默认注入 即不指定spring容器里面的名字 匹配规则:先通过属性的名字查找 再通过属性类型与实现类类型匹配查找 当有两个实现类会报错 2.通过指定 ...

  7. spring注解方式注入bean

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

  8. 【初识Spring】对象(Bean)实例化及属性注入(注解方式)

    通过xml的方式进行对象的实列化或属性注入或许有一些繁琐,所以在开发中常用的方式更多是通过注解的方式实现对象实例化和属性注入的. 开始之前 1.导入相关的包(除了导入基本的包还要导入aop的包): 创 ...

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

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

随机推荐

  1. Differential Geometry之第十章极小曲面

    第十章.极小曲面 1.极小图 Animation showing the deformation of a helicoid into a catenoid. Animation of Scherk' ...

  2. 梯度下降算法到logistic回归

    http://sbp810050504.blog.51cto.com/2799422/1608064/ http://blog.csdn.net/dongtingzhizi/article/detai ...

  3. MyBatis 是一款优秀的持久层框架

    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...

  4. 转载:CSS3图标图形生成技术个人攻略

    原始地址:http://segmentfault.com/a/1190000000481320 出处:http://www.zhangxinxu.com/wordpress/?p=4113

  5. phalcon下拉列表

    <?php echo Phalcon\Tag::selectStatic("gender", array(0 => "Male", 1 => ...

  6. 如何用MathType编辑出积分符号

    MathType由于能够编辑出众多的数学符号而备受理工科学生与老师的喜爱.利用它,你可以在文档中随意编写出你想要的公式.对于从来没有用过公式编辑器的人来说,在文档中看到那些复杂的数学公式时总是会为之惊 ...

  7. MathType二次偏导怎么表示

    求导以及求偏导运算在数学中是很重要的一个部分,尤其是在高等数学中,基本都由函数的导数与偏导组成,很多公式定理也是关于这方面的,如果少了这一部分,数学将会黯然失色.因此在文档中涉及到这些内容时,必然会少 ...

  8. VS------快捷键一览

    1. 属性封装快捷键:Ctrl + R + E

  9. iOS Web开发

    1.让web页面的输入框是数字键盘 html 中 input 的 type = "tel"

  10. Struts2的CRUD操作

    Struts之CRUD 1何为CRUD:CRUD代表的是一个框架的Create(增),Read(读取),update(更新),Delete(删除) 2怎么做呢?? 其实Struts2的CRUD与现实的 ...