1、在相关的包下创建 Annotation ,右键 -----> Other --------> 如下图所示
选中之后,点击 Next ,对文件进行命名,代码如下:
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 TestResource {
public String name() default "";
}
(1)、java中元注解有四个: @Retention @Target @Document @Inherited;
<1>、 @Retention:注解的保留位置
@Retention(RetentionPolicy.SOURCE) 注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
@Retention(RetentionPolicy.RUNTIME) 注解会在class字节码文件中存在,在运行时可以通过反射获取到
<2>、@Target:注解的作用目标
@Target(ElementType.TYPE) //接口、类、枚举、注解
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
具体的可以查看:http://www.cnblogs.com/Gordon-YangYiBao/archive/2012/08/07/2626340.html
2、修改 TestClassPathXMLApplicationContext 类,代码如下:
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.List;
import java.util.Map;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
/**
* 模拟spring
* @author Administrator
*
*/
public class TestClassPathXMLApplicationContext {
List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
Map<String, Object> sigletons = new HashMap<String, Object>();
public TestClassPathXMLApplicationContext(String filename){
readFile(filename);
instanceBeans();
annotationInject();
injectObj();
}
private void annotationInject() {
for(String beanName : sigletons.keySet()){//循环所有的bean对象
//得到bean对象
Object bean = sigletons.get(beanName);
if(null != bean){
try {
// 得到类的属性描述
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDescriptor propertydesc : ps){
//获取属性的setter方法
Method setter = propertydesc.getWriteMethod();
//判断setter 方法是否存在,并且通过反射机制判断setter 方法是否存在注解
if(null != setter && setter.isAnnotationPresent(TestResource.class)){
//获取注解
TestResource resource = setter.getAnnotation(TestResource.class);
Object valName = null;
if(null != resource.name() && !"".equals(resource.name())){
//通过注解中的name属性,将对象从 sigletons 集合中取出来
valName = sigletons.get(resource.name());
}else{
valName = sigletons.get(resource.name());
if(null == valName){
for(String key : sigletons.keySet()){//循环所有的bean对象
//判断类型是否匹配
if(propertydesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){
valName = sigletons.get(key);
break;
}
}
}
}
setter.setAccessible(true); //如果setter方法是私有的,经调用该方法处理表示可以访问
setter.invoke(bean, valName);
}
}
Field[] fields = bean.getClass().getFields();
for(Field field : fields){
if(null != field && field.isAnnotationPresent(TestResource.class)){
//获取注解
TestResource resource = field.getAnnotation(TestResource.class);
Object valName = null;
if(null != resource.name() && !"".equals(resource.name())){
//通过注解中的name属性,将对象从 sigletons 集合中取出来
valName = sigletons.get(resource.name());
}else{
valName = sigletons.get(field.getName());
if(null == valName){
for(String key : sigletons.keySet()){//循环所有的bean对象
//判断类型是否匹配
if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){
valName = sigletons.get(key);
break;
}
}
}
}
field.setAccessible(true); //如果setter方法是私有的,经调用该方法处理表示可以访问
field.set(bean, valName);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 为 bean 对象属性注入值
*/
private void injectObj() {
for(BeanDefinition beanDefinition : beanDefines){
//通过 id 得到 bean 元素所指向的类
Object bean = sigletons.get(beanDefinition.getId());
if(null != bean){ //判断类是否存在
try{
// 得到类的属性描述
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDefinition propertyDefinition : beanDefinition.getProperty()){
for(PropertyDescriptor propertydesc : ps){
if(propertyDefinition.getName().equals(propertydesc.getName())){
//获取属性的setter方法
Method setter = propertydesc.getWriteMethod();
if(null != setter){ //容错处理
Object value = null;
/**
* 判断 ref 是否存在,如果存在则注入依赖对象,否则注入基本类型
*/
if(null != propertyDefinition.getRef() && !"".equals(propertyDefinition.getRef())){
value = sigletons.get(propertyDefinition.getRef());
}else{
/**
* 将得到的值转化为所要的类型
*/
value = ConvertUtils.convert(propertyDefinition.getValue(), propertydesc.getPropertyType());
}
setter.setAccessible(true); //如果setter方法是私有的,经调用该方法处理表示可以访问
setter.invoke(bean, value);
}
break;
}
}
}
}catch(Exception e){
}
}
}
}
/**
* 实例化bean对象
*/
private void instanceBeans() {
for(BeanDefinition beanDefinition : beanDefines){
try {
/**
* 通过反射技术将bean实例化
*/
if(null != beanDefinition.getClassName() && !"".equals(beanDefinition.getClassName().trim())){
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
*/
private void readFile(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>();
//加入命名空间,xml 文件中的命名空间为 xmlns="http://www.springframework.org/schema/beans" ,我们这里将它放入到ns中
nsMap.put("ns", "http://www.springframework.org/schema/beans");
//创建beans/bean查询路径,通过命名空间找到,该命名空间下的节点元素
XPath xsub = document.createXPath("//ns:beans/ns:bean");
//设置命名空间
xsub.setNamespaceURIs(nsMap);
//获取文档下所有的bean节点
@SuppressWarnings("unchecked")
List<Element> beans = xsub.selectNodes(document);
for(Element element : beans){
String id = element.attributeValue("id");
String className = element.attributeValue("class");
BeanDefinition beanDefine = new BeanDefinition(id, className);
//创建查询路径
XPath propertysub = element.createXPath("ns:property");
//设置命名空间
propertysub.setNamespaceURIs(nsMap);
//获取当前元素下的节点
@SuppressWarnings("unchecked")
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 propertyDefinition = new PropertyDefinition(propertyName, propertyRef, propertyValue);
beanDefine.getProperty().add(propertyDefinition);
}
beanDefines.add(beanDefine);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 获取bean实例
* @param beanName
* @return
*/
public Object getBean(String beanName){
return sigletons.get(beanName);
}
public void initStr(){
System.out.append("ff");
}
}
3、PresonServiceImpl 类的代码如下:
package com.learn.service.impl;
import junit.test.TestResource;
import com.learn.dao.PresonDao;
import com.learn.service.PresonService;
/**
* 业务层
* @author Administrator
*
*/
public class PresonServiceImpl implements PresonService {
private PresonDao presonDao;
private String name;
public PresonServiceImpl(){
}
public PresonServiceImpl(PresonDao presonDao, String name) {
this.presonDao = presonDao;
this.name = name;
}
@TestResource
public void setPresonDao(PresonDao presonDao) {
this.presonDao = presonDao;
}
/* (non-Javadoc)
* @see com.learn.service.impl.PresonService#save()
*/
@Override
public void save(){
//System.out.println("name="+name);
presonDao.add();
}
}
将原来的 @Resource 替换成 @TestResource。
4、TestSpring类 代码如下:
package junit.test;
import com.learn.service.PresonService;
public class TestSpring {
@Test
public void initContainerSpring() {
TestClassPathXMLApplicationContext ctx = new TestClassPathXMLApplicationContext("com//learn//spring//learn1.xml");
PresonService personService = (PresonService)ctx.getBean("personService");
personService.save();
}
}
5、xml 文件不变。测试。
浙公网安备 33010602011771号