容器接口

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 我们要完成自动装配,那么就要有一个存放bean对象的容器,然后要有装配的注解,那么哪些类该被存到容器呢,在spring中我们使用过@Service、@Resource等,看下面的代码,你也可以做到。

  我们要完成自动装配,那么就要有一个存放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<StringObject> beansMap = new HashMap<StringObject>();
	
	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 = (Bc.getBean(B.classBeanType.SINGLE);
		b.hehe();
		System.out.println(b.getQq());
		System.out.println("==================");
		B b2 = (Bc.getBean(B.classBeanType.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://www.wanzhuanlewangba.com/

www.baiyi1.cn

聚享游 http://www.tiantanzuan.com/站内文章,如需转载,请保留作者和出处(云栖社区),并邮件通知云栖社区(yqeditor@list.alibaba-inc.com)。

目录
相关文章
|
3月前
|
存储 算法 Java
容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)(中)
容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)
51 0
|
3月前
|
安全 Java 编译器
容器【泛型类、泛型接口、泛型方法 、泛型方法与可变参数 】(一)-全面详解(学习总结---从入门到深化)
容器【泛型类、泛型接口、泛型方法 、泛型方法与可变参数 】(一)-全面详解(学习总结---从入门到深化)
27 0
|
存储 Kubernetes Cloud Native
一文读懂容器存储接口 CSI
在《一文读懂 K8s 持久化存储流程》一文我们重点介绍了 K8s 内部的存储流程,以及 PV、PVC、StorageClass、Kubelet 等之间的调用关系。接下来本文将将重点放在 CSI(Container Storage Interface)容器存储接口上,探究什么是 CSI 及其内部工作原理。
一文读懂容器存储接口 CSI
|
2月前
|
存储 算法 安全
容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)
容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)
27 0
|
3月前
|
编译器 C++ 容器
【C++】vector容器接口要点的补充
【C++】vector容器接口要点的补充
|
3月前
|
存储 容器
容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)(下)
容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)
19 0
|
3月前
|
存储 算法 安全
容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)(上)
容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)
20 0
|
3月前
|
存储 安全 索引
容器【容器介绍、Set接口介绍、 HashSet容器的使用、TreeSet容器的使用】(三)-全面详解(学习总结---从入门到深化)
容器【容器介绍、Set接口介绍、 HashSet容器的使用、TreeSet容器的使用】(三)-全面详解(学习总结---从入门到深化)
14 0
|
10月前
|
算法 C++ 容器
<C++> list容器本质|常用接口|自定义排序规则(下)
<C++> list容器本质|常用接口|自定义排序规则
79 0
|
10月前
|
存储 C++ 容器
<C++> list容器本质|常用接口|自定义排序规则(上)
<C++> list容器本质|常用接口|自定义排序规则
77 0