深入理解注释@Resource注入
@Resource默认是按照名称,名称可通过@Resource的name属性进行指定,如果没有指定name属性,当注解标注在字段上即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在setter方法上,则默认属性为bean名称寻找依赖对象。
模拟@Resource实现
1、首先我们写一个自己的注释
/**
* 书本:【SSH】
* 功能:实现spring里面的注解注入功能,个人实现
* 文件:Cutter_pointResource.java
* 时间:2015年3月18日21:17:24
* 作者:cutter_point
*/
package junit.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) //制定注解保留的范围是运行的时候
@Target({ElementType.FIELD, ElementType.METHOD}) //注解的地方是字段和属性
public @interface Cutter_pointResource
{
public String name() default ""; //name属性默认是空字符串
}
2、然后先相应的bean里面添加自己的注解在前面
package cn.itcast.service.impl;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Resource;
import junit.test.Cutter_pointResource;
import cn.itcast.dao.PersonDao;
import cn.itcast.service.PersonService;
public class PersonServiceBean implements PersonService {
// @Resource private PersonDao personDao; //通过注释来进行注入
@Cutter_pointResource private PersonDao personDao;
private String name = "cutter_point";
public PersonServiceBean()
{
// TODO Auto-generated constructor stub
}
//使用set方法注释注入
// @Cutter_pointResource
// public void setPersonDao(PersonDao personDao)
// {
// this.personDao = personDao;
// }
/**
* @author xiaofeng
* @param 这个是可以生成的构造器
*/
public PersonServiceBean(PersonDao personDao, String name)
{
this.personDao = personDao;
this.name = name;
}
public void save(){
System.out.println(name);
personDao.add();
}
}
3、然后在我们读取XML文档bean.xml的时候,注意注解注入,也就是在对象注入之前检测一下是否有注解,有的话就注入
this.readXML(filename);
this.instanceBeans();
this.annotationInject(); //注解注入
this.injectObject(); //注入对象
然后具体实现注解的注入
/**
* 通过注解实现注入依赖对象
*/
private void annotationInject()
{
for(String beanName : sigletons.keySet()) //吧map里面的bean的id号一个一个地取出来
{
Object bean = sigletons.get(beanName); //根据id取出相应的bean对象
if(bean!=null)
{
try
{
//取得这个bean实例化的属性信息,这个是方法前面加了
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); //一个容器
for(PropertyDescriptor properdesc : ps) //一个属性一个属性取出来
{
Method setter = properdesc.getWriteMethod();//获取属性的setter方法
if(setter!=null && setter.isAnnotationPresent(Cutter_pointResource.class)) //看看这个set函数上面是否有这个注解
{
Cutter_pointResource resource = setter.getAnnotation(Cutter_pointResource.class); //取得这个注解
Object value = null; //量这个属性
if(resource.name()!=null && !"".equals(resource.name()))
{
value = sigletons.get(resource.name()); //name属性制定的是bean的名称
}
else
{
value = sigletons.get(properdesc.getName()); //根据字段的名称在容器中寻找
if(value==null)
{
for(String key : sigletons.keySet())
{
//根据字段的类型进行寻找
if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass()))
{
value = sigletons.get(key);
break;
}
}
}
}
System.out.println("就是里面的方法前面加了注释");
setter.setAccessible(true); //运行访问私有的字符
setter.invoke(bean, value);//把引用对象注入到属性
}
}
//这个是对字段进行处理,数据成员前面加了注释
Field[] fields = bean.getClass().getDeclaredFields(); //bean的所有的字段数组
for(Field field : fields) //取出每个字段
{
if(field.isAnnotationPresent(Cutter_pointResource.class)) //字段上是否存在注解
{
Cutter_pointResource resource = field.getAnnotation(Cutter_pointResource.class);
Object value = null;
if(resource.name()!=null && !"".equals(resource.name()))
{
value = sigletons.get(resource.name());
}
else
{
value = sigletons.get(field.getName());
if(value==null)
{
for(String key : sigletons.keySet())
{
//根据字段的类型进行寻找
if(field.getType().isAssignableFrom(sigletons.get(key).getClass()))
{
value = sigletons.get(key);
break;
}
}
}
}
System.out.println("字段注解注入,就是相应的数据成员加上了注释");
field.setAccessible(true);//允许访问private字段
field.set(bean, value);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
4、对于XML文档进行操作的全部代码
package junit.test;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
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;
/**
* 传智传客版容器
*
*/
public class ItcastClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>(); //存放所有的bean对象
public ItcastClassPathXMLApplicationContext(String filename)
{
this.readXML(filename);
this.instanceBeans();
this.annotationInject();
this.injectObject(); //注入对象
}
/**
* 通过注解实现注入依赖对象
*/
private void annotationInject()
{
for(String beanName : sigletons.keySet()) //吧map里面的bean的id号一个一个地取出来
{
Object bean = sigletons.get(beanName); //根据id取出相应的bean对象
if(bean!=null)
{
try
{
//取得这个bean实例化的属性信息,这个是方法前面加了
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); //一个容器
for(PropertyDescriptor properdesc : ps) //一个属性一个属性取出来
{
Method setter = properdesc.getWriteMethod();//获取属性的setter方法
if(setter!=null && setter.isAnnotationPresent(Cutter_pointResource.class)) //看看这个set函数上面是否有这个注解
{
Cutter_pointResource resource = setter.getAnnotation(Cutter_pointResource.class); //取得这个注解
Object value = null; //量这个属性
if(resource.name()!=null && !"".equals(resource.name()))
{
value = sigletons.get(resource.name()); //name属性制定的是bean的名称
}
else
{
value = sigletons.get(properdesc.getName()); //根据字段的名称在容器中寻找
if(value==null)
{
for(String key : sigletons.keySet())
{
//根据字段的类型进行寻找
if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass()))
{
value = sigletons.get(key);
break;
}
}
}
}
System.out.println("就是里面的方法前面加了注释");
setter.setAccessible(true); //运行访问私有的字符
setter.invoke(bean, value);//把引用对象注入到属性
}
}
//这个是对字段进行处理,数据成员前面加了注释
Field[] fields = bean.getClass().getDeclaredFields(); //bean的所有的字段数组
for(Field field : fields) //取出每个字段
{
if(field.isAnnotationPresent(Cutter_pointResource.class)) //字段上是否存在注解
{
Cutter_pointResource resource = field.getAnnotation(Cutter_pointResource.class);
Object value = null;
if(resource.name()!=null && !"".equals(resource.name()))
{
value = sigletons.get(resource.name());
}
else
{
value = sigletons.get(field.getName());
if(value==null)
{
for(String key : sigletons.keySet())
{
//根据字段的类型进行寻找
if(field.getType().isAssignableFrom(sigletons.get(key).getClass()))
{
value = sigletons.get(key);
break;
}
}
}
}
System.out.println("字段注解注入,就是相应的数据成员加上了注释");
field.setAccessible(true);//允许访问private字段
field.set(bean, value);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
/**
* 为bean对象的属性注入值
*/
private void injectObject()
{
for(BeanDefinition beanDefinition : beanDefines)
{
Object bean = sigletons.get(beanDefinition.getId()); //取出所有的实例化
if(bean!=null)
{
try
{
//Introspector.getBeanInfo(bean.getClass())取得类的信息
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); //后面这个函数是取得相应的属性信息
for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys())
{
for(PropertyDescriptor properdesc : ps)
{
if(propertyDefinition.getName().equals(properdesc.getName()))
{
Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private
if(setter!=null)
{
Object value = sigletons.get(propertyDefinition.getRef());
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
break;
}
}
}
}
catch (Exception e)
{
}
}
}
}
/**
* 完成bean的实例化,吧所有的bean放到sigleton里面,并实例化保存
*/
private void instanceBeans()
{
for(BeanDefinition beanDefinition : beanDefines)
{
try
{
if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))
sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
/**
* 读取xml配置文件
* @param filename
*/
private void readXML(String filename)
{
SAXReader saxReader = new SAXReader();
Document document=null;
try
{
URL xmlpath = this.getClass().getClassLoader().getResource(filename); //获取xml文档的路径
document = saxReader.read(xmlpath); //读取xml文档
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);//获取文档下所有bean节点
for(Element element: beans)
{
String id = element.attributeValue("id");//获取id属性值
String clazz = element.attributeValue("class"); //获取class属性值
BeanDefinition beanDefine = new BeanDefinition(id, clazz);
//-------------------------------------------------------------------------------
XPath propertysub = element.createXPath("ns:property");
propertysub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> propertys = propertysub.selectNodes(element);
for(Element property : propertys)
{
String propertyName = property.attributeValue("name");
String propertyref = property.attributeValue("ref");
PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref);
beanDefine.getPropertys().add(propertyDefinition);
}
beanDefines.add(beanDefine);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* 获取bean实例
* @param beanName
* @return
*/
public Object getBean(String beanName){
return this.sigletons.get(beanName);
}
}
5、最后运行结果
项目图