b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

线程安全问题代码 Spring框架学习总结(理论篇——单例模式)(3)

电脑杂谈  发布时间:2018-02-17 07:07:57  来源:网络整理

?? ?? 这种方式是基于饿汉式的扩展(读者朋友也可以自行根据懒汉式完成注册表模式),工具类加载时为所有已经注册的类创建实例,并将实例存入集合中,调用方调用getInstance方法即可获得对应类的实例。

?? ?? 对于以上六种单例模式的实现,各有其最合适的使用方式,同样也可以交叉使用。另外,单例模式还有其他很多种实现方式,这里我们不一一列出,感兴趣的朋友可以自行研究。

?? ?? 本章主要内容已结束,作为拓展,我们基于以上简单注册表式创建实例的思想,将注册的方式改为XML配置文件中注册,即可实现一个简单功能的容器,这里贴出部分代码,代码未经整理重构,所以较冗长,且可能存在漏洞,感兴趣的朋友可以作为实现简单容器的参考,如果有问题感谢留言指出。

package runnable;

import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
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.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import annotation.Mark;
import test.packages.son02.User02;

/**
 * 简单的容器实现
 * @author Elio
 */
public class Util {
	
	private Element root;
	private List<Element> beans;
	private static Map<String, Object> beansMap=new HashMap<String, Object>();
	
	public static void main(String[] args) throws Exception{
		Util util=new Util("utils.xml");
		
		User02 u02=util.getBean("user02", User02.class);
		System.out.println(u02);
		
		System.out.println(beansMap);
		util.destroy();
	}	
	
	public Util() {
		super();
	}
	
	/*
	* @param file_Xml 配置文件的路径及名称
	*/
	public Util(String file_Xml) {
		super();
		loadXml(file_Xml);
		init();
	}
	
	private void loadXml(String file_Xml) {
		SAXReader reader=new SAXReader();
		Document doc;
		try {
			doc = reader.read(getClass().getClassLoader().getResource(file_Xml));
			root=doc.getRootElement();
			beans=root.elements();
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}

	/*
	 * 初始化函数,会直接加载xml配置文件
	 */
	private void init(){
		this.createInstanceByXml();
	}
	
	/*
	 * 销毁方法,调用此方法会执行所有在配置文件中注册过的销毁方法
	 */
	public void destroy(){
		for(Element bean:beans) {
			String destroy_methodName=bean.attributeValue("destroy-method");
			if(destroy_methodName!=null) {
				String classId=bean.attributeValue("id");
				if(beansMap.containsKey(bean.attributeValue("id"))) {
					Class cls;
					try {
						cls = Class.forName(bean.attributeValue("class"));
						Method destroy_method=cls.getMethod(destroy_methodName);
						destroy_method.invoke(getBean(classId, cls));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		beansMap.clear();
		beansMap=null;
	}
	
	/*
	 * 获取实例的方法
	 */
	public Object getBean(String classId){
		if(beansMap.containsKey(classId)){
			return beansMap.get(classId);
		}else{
			for(Element bean:beans){
				if(classId.equals(bean.attributeValue("id"))){
					Object obj=createInstanceByRef(classId);
					addBeanToMap(bean, obj);
					return obj;
				}
			}
		}
		return null;
	}
	
	/*
	 * 获取携带类型信息的实例
	 */
	public <T>T getBean(String classId,Class<T> cls){
		return (T)this.getBean(classId);
	}
	
	/*
	 * 通过读取xml文件创建对象
	 */
	private void createInstanceByXml(){
			boolean default_lazy_init=Boolean.parseBoolean(root.attributeValue("default-lazy-init"));
			for(Element bean:beans) {
				boolean lazy_init;
				if(bean.attributeValue("lazy-init")==null) {
					lazy_init=default_lazy_init;
				}else {
					lazy_init=Boolean.parseBoolean(bean.attributeValue("lazy-init"));
				}
				if(!lazy_init&&!"prototype".equals(bean.attributeValue("scope"))
						&&bean.attributeValue("class")!=null) {
					createInstance(bean);
				}
			}
	}
	
	/*
	 * 通过property标签为实例赋值
	 */
	private void setValueByProperties(Element bean, Object obj) {
		List<Element> properties=bean.elements("property");
		for(Element property:properties){
			String parameterName=property.attributeValue("name");
			String setMethodName="set"+parameterName.substring(0,1).toUpperCase()+parameterName.substring(1);
			System.out.println(setMethodName);
			String parameterValue=property.attributeValue("value");
			String parameterRef=property.attributeValue("ref");
			Class cls=obj.getClass();
			Method[] methods=cls.getDeclaredMethods();
			for(Method method:methods){
				if(setMethodName.equals(method.getName())){
					try {
						if(parameterValue!=null){
							method.invoke(obj,parameterValue);
						}else{
							if(beansMap.containsKey(parameterRef)){
								method.invoke(obj, beansMap.get(parameterRef));
							}else{
								Object obj_ref=createInstanceByRef(parameterRef);
								addBeanToMap(bean, obj_ref);
								method.invoke(obj, obj_ref);
							}
						}
					} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
						e.printStackTrace();
					}
				}
			}
		}
		
	}

	/*
	 * 通过引用创建对象
	 */
	private Object createInstanceByRef(String ref){
			for(Element bean:beans) {
				if(ref.equals(bean.attributeValue("id"))){
					try {
						Object obj=null;
						if(bean.elements("constructor-arg").size()==0) {
							obj=Class.forName(bean.attributeValue("class")).newInstance();
							setValueByProperties(bean,obj);
						}else {
							obj=setValueByConstructor(bean);
							setValueByProperties(bean,obj);
						}
						addBeanToMap(bean, obj);
						return obj;
					} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
						e.printStackTrace();
					}
				}	
			}
			return null;
	}
	
	/*
	 * 通过bean对象创建实例
	 */
	private Object createInstance(Element bean){
		try {
			Object obj=null;
			if(bean.elements("constructor-arg").size()==0) {
				obj=Class.forName(bean.attributeValue("class")).newInstance();
				setValueByProperties(bean,obj);
			}else {
				obj=setValueByConstructor(bean);
				setValueByProperties(bean,obj);
			}
			addBeanToMap(bean, obj);
			return obj;
		} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/*
	 * 通过扫描包的形式创建对象
	 */
	private void createPackage(String packageName,Boolean createAll){
		String packagePath=packageName.replaceAll("\\.", "/");
		URL packageUrl=this.getClass().getClassLoader().getResource(packagePath);
		File pkgFile=new File(packageUrl.getPath());
		File[] files_class=pkgFile.listFiles(new FileFilter() {
			@Override
			public boolean accept(File file) {
				if(file.getName().endsWith(".class")){
					return true;
				}else if(file.isDirectory()){
					try {
						createPackage(packageName+"."+file.getName(),createAll);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				return false;
			}
		});
		for(File file:files_class){
			String className=file.getName().substring(0,file.getName().lastIndexOf("."));
			Object obj;
			if(createAll) {
				//创建包下的所有类的实例
				try {
					obj = Class.forName(packageName+"."+className).newInstance();
					String classId=className.substring(0,1).toLowerCase()+className.substring(1);
					beansMap.put(classId, obj);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}else {
				//只创建有Mark注解的类的实例
				try {
					Class<?> cls=Class.forName(packageName+"."+className);
					if(cls.isAnnotationPresent(Mark.class)){
						obj=cls.newInstance();
						String classId=className.substring(0,1).toLowerCase()+className.substring(1);
						beansMap.put(classId,obj);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
				
		}
	}
	
	/*
	 * 不指定是否全部创建时,只创建被标记的
	 */
	private void createPackage(String packageName) {
		this.createPackage(packageName, false);
	}
	
	/*
	 * 使用有参构造器创建对象时调用此方法 
	 */
	private Object setValueByConstructor(Element bean) {
		try {
			//加载该类
			Class<?> cls=Class.forName(bean.attributeValue("class"));
			//过的该bean标签下的constructor-atg标签
			List<Element> con_args=bean.elements("constructor-arg");
			//对constructor-arg标签进行排序,结果保存为Object类型
			List<Object> con_arg_values=new ArrayList<>();
			for(int i=0;i<con_args.size();i++){
				con_arg_values.add(null);
			}
			for(Element con_arg:con_args) {
				String value=con_arg.attributeValue("value");
				if(con_arg.attributeValue("index")!=null) {
					int index=Integer.parseInt(con_arg.attributeValue("index"));
					if(value!=null)
						con_arg_values.set(index,value);
					else{
						String ref=con_arg.attributeValue("ref");
						if(beansMap.containsKey(ref)){
							con_arg_values.set(index, getBean(ref));
						}else{
							createInstanceByRef(ref);
							con_arg_values.set(index, getBean(ref));
						}
					}
				}else {
					for(int i=0;i<con_args.size();i++){
						if(con_arg_values.get(i)==null) {
							if(value!=null){
								con_arg_values.set(i,value);
							}else{
								String ref=con_arg.attributeValue("ref");
								if(beansMap.containsKey(ref)){
									con_arg_values.set(i, getBean(ref));
								}else{
									Object obj=createInstanceByRef(ref);
									con_arg_values.set(i, obj);
								}
							}
							break;
						}
					}
				}
			}
			//获得该类的所有构造器
			Constructor<?>[] cons=cls.getDeclaredConstructors();
			for(Constructor<?> con:cons) {
				//按照constructor-arg标签的顺序,尝试执行每一个形参个数相同的构造器
				if(con.getParameterCount()==con_args.size()) {
					List<Object> parametersList=new ArrayList<>();
					Class<?>[] parameterTypes=con.getParameterTypes();
					for(int i=0;i<parameterTypes.length;i++) {
						addToParametersList(con_arg_values.get(i),parameterTypes[i],parametersList);
					}
					try {
						return con.newInstance(parametersList.toArray());   
					} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
							| InvocationTargetException e) {
						e.printStackTrace();
					}
				}
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/*
	 * 完成类型转换并将参数的值加入实参列表
	 */
	private void addToParametersList(Object obj,Class cls,List<Object> parametersList){
		String parameterType=cls.getName();
		String value=String.valueOf(obj);
		if("java.lang.String".equals(parameterType)) {
			parametersList.add(value);
		}else if("int".equals(parameterType)) {
			parametersList.add(Integer.parseInt(value));
		}else if("short".equals(parameterType)) {
			parametersList.add(Short.parseShort(value));
		}else if("long".equals(parameterType)) {
			parametersList.add(Long.parseLong(value));
		}else if("double".equals(parameterType)) {
			parametersList.add(Double.parseDouble(value));
		}else if("float".equals(parameterType)) {
			parametersList.add(Float.parseFloat(value));
		}else if("char".equals(parameterType)&&value.length()==1) {
			parametersList.add(value.charAt(0));
		}else if("boolean".equals(parameterType)) {
			parametersList.add(Boolean.parseBoolean(value));
		}else{
			parametersList.add(obj);
		}
	}
	
	/*
	 * 尝试将新创建的实例加入Map中
	 */
	private void addBeanToMap(Element bean,Object obj){
		if(!"prototype".equals(bean.attributeValue("scope"))){
			beansMap.put(bean.attributeValue("id"), obj);
		}
	}
	
}

?? ?? 我们在主方法中启动三个线程,并发访问获得SingletonTest类的实例并输出,运行结果有可能会出现获得的实例不唯一的情况(取决于计算机的当前状态,多试几次一定会出现线程安全问题):


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-81652-3.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...