Spring IOC 原理 ,Java 反射实例,自定义注解
Spring IOC 原理 和 Java 反射实例
——我一直不太信任自己的记忆力,所以我把它们都写下来
自从接触了Spring的各种思想后,真的是被各种设计征服了,当然Spring的各种设计基本上都需要扎实的java基础支持;比如SpringIOC(依赖注入,bean管理思想)运用到了Java注解、反射、xml等等。下面用一个实例来说明SpringIOC的原理。
在SpringMVC项目中,对DAO和service一般都是spring注解管理的,像@Service,@Respository,@Component等。项目用Maven管理,文章末尾有svn地址和下载地址,代码里只要稍微有点晦涩的地方都有注释,有java经验的应该都能看懂。下面是项目结构图
anntation包下面是对@Resource,@Respository,@Service 的注解实现类;util包下面是java反射的相关类,dao和service包见文思意。测试入口在src/test/java下面。
MySpring.class 是主要的逻辑类,模拟了SpringIOC的ApplicationContext,所有的注册过的bean都可以从这里获得。完整的类如下
package com.albert.AnnotationTest; import java.lang.reflect.Field; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; import com.albert.AnnotationTest.annotation.Resource; import com.albert.AnnotationTest.annotation.Respository; import com.albert.AnnotationTest.annotation.Service; import com.albert.AnnotationTest.dao.MyDao; import com.albert.AnnotationTest.service.MyService; import com.albert.AnnotationTest.util.AlbertUtil; import com.albert.AnnotationTest.util.ClassByPackage; /** * @author albert * 这个类模拟Spring ioc 和mvc * 所有注解过的bean都从这里取得 * */ public class MySpring { /** * 模拟Spring扫描的注解包 */ private final static String packageName = "com.albert.AnnotationTest"; /** * 存放注解的bean对象 */ private static Map<String,Object> beanMap = new HashMap<String, Object>(); static{ try { packageToScan(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } /** * 根据beanName从容器获取bean对象 * @param beanName * @return */ public static Object getBean(String beanName){ Object obj = null; obj = beanMap.get(beanName); return obj; } /** * 遍历包中的注解类 * @throws IllegalAccessException * @throws InstantiationException */ private static void packageToScan() throws InstantiationException, IllegalAccessException{ List<Class> clsList = ClassByPackage.getClasssFromPackage(packageName); //先加载dao for(Class cls : clsList){ //判断类是不是有@Respository注解 if(cls.isAnnotationPresent(Respository.class)){ String clsName = AlbertUtil.getBeanName(cls.getName()); //bean对象存入map beanMap.put(clsName, cls.newInstance()); } } //加载service,同时对其中@Resource注解的属性进行赋值 for(Class cls : clsList){ if( cls.isAnnotationPresent(Service.class)){ String clsName = cls.getName(); clsName = clsName.substring(clsName.lastIndexOf(".")+1, clsName.length()); beanMap.put(AlbertUtil.toLowerCaseFirstOne(clsName), cls.newInstance()); //扫描注解@Resource的属性并赋值 Field[] field = cls.getDeclaredFields(); for(Field f : field){ //判断属性是不是有@Resource注解 if(f.isAnnotationPresent(Resource.class)){ f.setAccessible(true); f.set(beanMap.get(AlbertUtil.getBeanName(cls.getName())), beanMap.get(f.getName())); } } } } } }
项目SVN地址:http://code.taobao.org/svn/AnnotationTestAlbert/