Spring中我们用到的功能实现:基于注解的Ioc自动装配
2014-06-26 15:54
926 查看
我们要完成自动装配,那么就要有一个存放bean对象的容器,然后要有装配的注解,那么哪些类该被存到容器呢,在spring中我们使用过@Service、@Resource等,看下面的代码,你也可以做到。
来看看这是一个简单的容器接口
这个容器提供了基础的存取方法,分别是获取bean对象和注册、是否包含bean,还有一个初始化的方法。
接下来我们来为容器做一个基本的实现。
在构造器里将扫描到的类加载到容器里,然后提供注册bean和获取bean的方法。
这个类是加载需要的类文件。还有几个代码文件没有贴出来,想看代码的等会打包自己看。
接下来我们看看这个测试,
运行结果:
好了,这样就基本完成了一个简单的ioc自动装配。有喜欢的朋友可以参考代码。点击下载
来看看这是一个简单的容器接口
/** * 容器接口 * @author:rex * @create_time:2014-6-26 * @version:V1.0 */ public interface Container { Object getBean(String name, BeanType beanType); Object getBean(Class<?> type, BeanType beanType); Set<?> getBeanNames(); Collection<?> getBeans(); boolean hasBean(Class<?> clazz); boolean hasBean(String name); void registBean(Class<?> clazz); void initWired(); }
这个容器提供了基础的存取方法,分别是获取bean对象和注册、是否包含bean,还有一个初始化的方法。
接下来我们来为容器做一个基本的实现。
import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import com.biezhi.ioc.BeanType; import com.biezhi.ioc.Container; import com.biezhi.ioc.anntation.Autowired; /** * 默认的bean容器实现 * @author:rex * @create_time:2014-6-26 * @version:V1.0 */ public class DefaultContainerImpl implements Container { //存放bean的容器 private final Map<String, Object> beansMap = new HashMap<String, Object>(); public DefaultContainerImpl() { //初始化加载bean ContainerLoader c = new ContainerLoader(this); c.init(); } @Override public Object getBean(String name, BeanType beanType) { try { if(beanType == BeanType.NEW) return Class.forName(name).newInstance(); } catch (Exception e) { e.printStackTrace(); } return beansMap.get(name); } @Override public Object getBean(Class<?> type, BeanType beanType) { try { if(beanType == BeanType.NEW) return type.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } Iterator<Object> it = this.beansMap.values().iterator(); while(it.hasNext()){ Object obj = it.next(); if(type.isAssignableFrom(obj.getClass())){ return obj; } } return null; } @Override public Set<?> getBeanNames(){ return beansMap.keySet(); } @Override public Collection<?> getBeans(){ return beansMap.values(); } @Override public boolean hasBean(Class<?> clz) { if(null != this.getBean(clz, null)){ return true; } return false; } @Override public boolean hasBean(String name){ if(null != this.getBean(name, null)){ return true; } return false; } /** * 注册一个bean对象到容器里 */ @Override public void registBean(Class<?> clazz){ String name = clazz.getCanonicalName(); try { if(!Modifier.isAbstract(clazz.getModifiers()) && !Modifier.isInterface(clazz.getModifiers())){ Object obj = clazz.newInstance(); beansMap.put(name, obj); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } /** * 初始化注入 */ @Override public void initWired(){ Iterator<Object> it = this.beansMap.values().iterator(); try { while(it.hasNext()){ Object obj = it.next(); Field[] fields = obj.getClass().getDeclaredFields(); for(Field field : fields){ Autowired autowired = field.getAnnotation(Autowired.class); if(null != autowired){ //要注入的字段 Object wiredField = this.getBean(field.getType(), null); if(null == wiredField){ throw new RuntimeException("Unable to load "+field.getType().getCanonicalName()+"!"); } boolean accessible = field.isAccessible(); field.setAccessible(true); field.set(obj, wiredField); field.setAccessible(accessible); } } } } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
在构造器里将扫描到的类加载到容器里,然后提供注册bean和获取bean的方法。
import java.io.File; import java.io.FileFilter; import java.util.HashSet; import java.util.Set; import com.biezhi.ioc.Container; import com.biezhi.ioc.anntation.Service; import com.biezhi.ioc.util.ClassHelper; /** * 加载容器bean * @author:rex * @create_time:2014-6-26 * @version:V1.0 */ public class ContainerLoader { private Container container; public ContainerLoader(Container container) { this.container = container; } public void init(){ //加载要扫描的包,这里可以使用配置文件,我们就默认扫描所有类 Set<String> packages = getPackages(); for(String pack : packages){ scanPack(pack); } //初始化注入 container.initWired(); } private void scanPack(String pack){ Set<Class<?>> classes = ClassHelper.scanPackage(pack); for(Class<?> clazz : classes){ // 这里我只把带有@Service注解的存进去了,你也可以存其他的或者全部 Service service = clazz.getAnnotation(Service.class); if(null != service){ //将扫描到的对象保存到容器中 container.registBean(clazz); } } } /** * 获取当前classes的包名称 * @author:rex * @return */ private Set<String> getPackages(){ Set<String> packages = new HashSet<String>(); String appPath = ContainerLoader.class.getResource("/").getPath(); File classDir = new File(appPath); // 如果存在 就获取包下的所有文件 包括目录 File[] dirfiles = classDir.listFiles(new FileFilter() { public boolean accept(File file) { return file.isDirectory(); } }); for(File f : dirfiles){ packages.add(f.getName()); } return packages; } }
这个类是加载需要的类文件。还有几个代码文件没有贴出来,想看代码的等会打包自己看。
接下来我们看看这个测试,
@Service public class A { String name = "菊花"; public void say(){ System.out.println("hello, I,m rex !"); } }
@Service public class B { @Autowired private A a; private String qq = "3838438"; public void hehe(){ a.say(); System.out.println("请问您是" + a.name + "吗?"); } public String getQq(){ return this.qq; } }
public class Test { public static void main(String[] args) { Container c = new DefaultContainerImpl(); c.initWired(); //System.out.println(c.getBeanNames()); B b = (B) c.getBean(B.class, BeanType.SINGLE); b.hehe(); System.out.println(b.getQq()); System.out.println("=================="); B b2 = (B) c.getBean(B.class, BeanType.NEW); b2.hehe(); } }
运行结果:
hello, I,m rex ! 请问您是菊花吗? 3838438 ================== Exception in thread "main" java.lang.NullPointerException at com.biezhi.ioc.test.B.hehe(B.java:15) at com.biezhi.ioc.test.Test.main(Test.java:18)
好了,这样就基本完成了一个简单的ioc自动装配。有喜欢的朋友可以参考代码。点击下载
相关文章推荐
- Java的注解机制——Spring自动装配的实现原理
- 使用spring注解 自动装配以及自动扫描机制 实现零xml配置的前提
- Java的注解机制——Spring自动装配的实现原理
- Java的注解机制——Spring自动装配的实现原理
- 基于Spring@Autowired注解与自动装配详谈
- Java的注解机制——Spring自动装配的实现原理
- 【Java.Spring.Core】【IoC】基于注解的Bean装配(非XML配置)
- spring 基于注解的自动装配
- Spring学习3—控制反转(IOC)基于Annotation(注解)的依赖注入实现
- Java的注解机制——Spring自动装配的实现原理
- spring-使用注解实现Bean自动装配1
- Java的注解机制——Spring自动装配的实现原理
- 基于注解整合struts2与spring的时候如果不引入struts2-spring-plugin包自动装配无效
- Spring容器拆分、自动装配和依赖检查机制,基于注解的sessionFactory
- 使用spring注解 自动装配以及自动扫描机制 实现零xml配置的前提
- spring、IoC控制反转和DI依赖注入入门、基于XML的Bean装配、基于注解的Bean装配
- spring-使用注解实现Bean自动装配2
- 【JavaWeb-23】spring、IoC控制反转和DI依赖注入入门、基于XML的Bean装配、基于注解的Bean装配
- Spring入门(基于Java的容器注解之@Scope和基于泛型的自动装配)
- Spring(四)基于注解配置IOC容器&基于注解实现声明式事务