博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring中我们用到的功能实现:基于注解的Ioc自动装配
阅读量:6088 次
发布时间:2019-06-20

本文共 6056 字,大约阅读时间需要 20 分钟。

  我们要完成自动装配,那么就要有一个存放bean对象的容器,然后要有装配的注解,那么哪些类该被存到容器呢,在spring中我们使用过@Service、@Resource等,看下面的代码,你也可以做到。

    来看看这是一个简单的容器接口

/** * 容器接口 * @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
 beansMap = new HashMap
(); 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
 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 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
 packages = getPackages(); for(String pack : packages){ scanPack(pack); } //初始化注入 container.initWired(); } private void scanPack(String pack){ Set
> 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
 getPackages(){ Set
 packages = new HashSet
(); 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; }}

    这个类是加载需要的类文件。还有几个代码文件没有贴出来,想看代码的等会打包自己看。

    接下来我们看看这个测试,

    

@Servicepublic class A {	String name = "菊花";		public void say(){		System.out.println("hello, I,m rex !");	}}

@Servicepublic 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自动装配。有喜欢的朋友可以参考代码。

转载地址:http://hvtwa.baihongyu.com/

你可能感兴趣的文章
通过思科模拟器CISCO PACKET TRACER学习网络12——静态NAT
查看>>
【12c OCP】CUUG OCP认证071考试原题解析(36)
查看>>
MongoDB、Hbase、Redis等NoSQL优劣势、应用场景
查看>>
Ubuntu下面MySQL的参数文件my.cnf浅析
查看>>
Tesra超算网络,解决AI开发困境
查看>>
The Quest Panel&obtain RS3gold free 900M runescape
查看>>
京东与万事达卡发布报告 移动支付战争C端转向B端
查看>>
screen命令详解
查看>>
使用 malloc后free出错 错误所在
查看>>
CentOS 搭建docker私有仓库实践
查看>>
VMware下安装QT Creator
查看>>
mysql从库出错
查看>>
vbs技巧
查看>>
Install Piwik 2.7 on CentOS 6.5
查看>>
xtrabackup备份和恢复MySQL
查看>>
Zabbix3.0.2监控Mongodb性能状态
查看>>
maven创建web项目
查看>>
允许Key重复的Map - IdentityHashMap
查看>>
Class文件解读(一)
查看>>
php 如何使用curl_file_create
查看>>