JSON配置文件的数据结构:
package light.zhang.ioc.bean; import java.io.Serializable; import java.util.List; import lombok.Data; import lombok.ToString; /** * 数据结构 * @author witts */ @Data @ToString public class Beandefinition implements Serializable{ /** * 序列ID */
private static final long serialVersionUID = -1723354830429118453L; /**BeanName参数**/
private String beanName; private String className; private String interfaceName; private List<ConstructorArg> ConstructorArgs; private List<PropertyArg> PropertyArgs; }
参数注入类:
package light.zhang.ioc.bean; import java.io.Serializable; import lombok.Data; @Data public class ConstructorArg implements Serializable { private static final long serialVersionUID = -1094744504486782050L; private String ref; }
package light.zhang.ioc.bean; import java.io.Serializable; public class PropertyArg implements Serializable { private static final long serialVersionUID = 4398781604716858284L; }
读取json配置文件:
package light.zhang.ioc.client; import java.io.InputStream; import java.util.List; import com.fasterxml.jackson.core.type.TypeReference; import light.zhang.ioc.bean.Beandefinition; import light.zhang.ioc.core.ApplicationContextFactory; import light.zhang.ioc.utils.JsonUtils; /** * 通过json格式的方式来存储注册信息,然后让IOC容器管理对象 * @author witts */
public class JsonApplicationContext extends ApplicationContextFactory { private String fileName; public JsonApplicationContext(String fileName) { this.fileName = fileName; initFile(); } private void initFile(){//读取文件,并注册到容器
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);//读取配置文件信息
List<Beandefinition> beanDefinitions = JsonUtils.readValue(is,new TypeReference<List<Beandefinition>>(){}); if(beanDefinitions != null && !beanDefinitions.isEmpty()) { for (Beandefinition beanDefinition : beanDefinitions) { registerBean(beanDefinition.getBeanName(), beanDefinition);//注册
} } } }
通过名称得到bean:
package light.zhang.ioc.core; import light.zhang.ioc.exception.CreateBeanException; import light.zhang.ioc.exception.LoadBeanException; public interface ApplicationContext { /** * 通过bean获取到注册的实例信息 * @param name * @throws Exception * @throws LoadBeanException * @throws CreateBeanException */
public Object getBean(String name) throws IllegalAccessException; }
负责bean生命周期管理,加载-实例-注册-销毁等
package light.zhang.ioc.core; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import light.zhang.ioc.bean.Beandefinition; import light.zhang.ioc.bean.ConstructorArg; import light.zhang.ioc.exception.CreateBeanException; import light.zhang.ioc.exception.LoadBeanException; import light.zhang.ioc.utils.BeanUtils; import light.zhang.ioc.utils.ClassLoaderUtils; import light.zhang.ioc.utils.ReflectionUtils; /** * 主要负责对加载到Map里面的对象取舍 beanDefineMap 存储的是对象的名称和对象对应的数据结构的映射。bean 用于保存 * beanName和实例化之后的对象。 容器初始化的时候,会调用 BeanRegisterFactoryImpl.registerBean 方法。把 * 对象的 Beandefinition 数据结构,存储起来 当我们调用 getBean() 的方法的时候。会先到 beanMap * 里面查找,有没有实例化好的对象。如果没有, 就会去beanDefineMap查找这个对象对应的 * BeanDefination。再利用DeanDefination去实例化一个对象。 对象实例化成功以后,我们还需要注入相应的参数,调用 * populatebean()这个方法。在 populateBean 这个方法中, 会扫描对象里面的Field,如果对象中的 Field * 是我们IoC容器管理的对象,那就会调用 我们上文实现的 ReflectionUtils.injectField来注入对象。 * 一切准备妥当之后,我们对象就完成了整个 IoC 流程。最后这个对象放入 beanMap 中,方便下一次使用。 所以我们可以知道 BeanFactory 是管理和生成对象的地方。 */
public class ApplicationContextFactory implements ApplicationContext { private static final Logger logger=LoggerFactory.getLogger(ApplicationContextFactory.class); private static final ConcurrentHashMap<String, Object> beanMap = new ConcurrentHashMap<String, Object>(); private static final ConcurrentHashMap<String, Beandefinition> undefineMap = new ConcurrentHashMap<String, Beandefinition>(); private static final Set<Object> beanNameSet = Collections.synchronizedSet(new HashSet<Object>());// 同步的hash set
@Override public Object getBean(String name) throws IllegalAccessException { Object bean = null; bean = beanMap.get(name);// 在已经注册过的情况下通过名称获取注册的实例
if (null != bean) { return bean; } bean = createBean(undefineMap.get(name)); // 如果没有实例化,那就需要调用createBean来创建对象,第一次加载的情况
if (bean != null) { // 对象创建成功以后,注入对象需要的参数
populatebean(bean); // 再把对象存入Map中方便下次使用。
beanMap.put(name, bean); } // 结束返回
logger.debug("This "+name+" is managed by ioc!!!"); return bean; } /** * 注册bean到IOC容器里面 * * @param name * @param bean */
protected void registerBean(String name, Beandefinition bean) { undefineMap.put(name, bean);// 先注册
beanNameSet.add(name);// 添加注册信息
} /** * 主要负责对参数的初始化 * * @param bean * @throws IllegalAccessException * @throws Exception * @throws LoadBeanException * @throws CreateBeanException */
private void populatebean(Object bean) throws IllegalAccessException { Field[] fields = bean.getClass().getSuperclass().getDeclaredFields();// 获取的代理对象信息
if (fields != null && fields.length > 0) {// 存在代理对象
for (Field field : fields) { String beanName = field.getName(); beanName = StringUtils.uncapitalize(beanName);// beanName字符串的第一个字符,转换为小写
if (beanNameSet.contains(field.getName())) {// 当包从IOC容器检测到注册信息之后
Object fieldBean = getBean(beanName);// 获取实例
if (fieldBean != null) { ReflectionUtils.initParamter(field, bean, fieldBean);// 初始化参数信息
} } } } } /** * 创建bean实例 * * @param beanDefinition * @return * @throws IllegalAccessException * @throws LoadBeanException * @throws Exception */
private Object createBean(Beandefinition beanDefinition) throws IllegalAccessException { if(null == beanDefinition) { try { throw new CreateBeanException(); } catch (CreateBeanException e) { e.printStackTrace(); } } String beanName = beanDefinition.getClassName(); Class<?> classInfo = ClassLoaderUtils.loaderClass(beanName); if (classInfo == null) { try { throw new LoadBeanException(); } catch (LoadBeanException e) { e.printStackTrace(); } } List<ConstructorArg> constructorArgs = beanDefinition.getConstructorArgs();// 获取参数列表
if (constructorArgs != null && !constructorArgs.isEmpty()) { List<Object> objects = new ArrayList<Object>(); for (ConstructorArg constructorArg : constructorArgs) { objects.add(getBean(constructorArg.getRef()));// ref引用信息
} try { return BeanUtils.instanceCreate(classInfo, classInfo.getConstructor(), objects.toArray());// 有参数的注入
} catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } } else { return BeanUtils.instanceCreate(classInfo, null, null);// 没有参数
} return null; } }
创建对象时异常
package light.zhang.ioc.exception; /** * 创建时异常 * @author witts * */
public class CreateBeanException extends Throwable { private static final long serialVersionUID = 1L; public CreateBeanException() { super("create bean fail,bean name is not found!!!"); } /** * 创建bean异常 * @param exc */
public CreateBeanException(String exc) { super(exc); } }
加载bean异常
package light.zhang.ioc.exception; /** * 加载时异常 * @author witts */
public class LoadBeanException extends Throwable{ private static final long serialVersionUID = 8520827571307312752L; @Override public synchronized Throwable fillInStackTrace() { return super.fillInStackTrace(); } public LoadBeanException() { super("load bean exception,bean not found!!!"); } public LoadBeanException(String message) { super(message); } }
bean工具类:
package light.zhang.ioc.utils; import java.lang.reflect.Constructor; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.NoOp; /** * 主要负责处理对BEAN的管理,BEAN的初创建,始化,状态管理 * @author witts */
public class BeanUtils { /** * 动态代理,并创建类 * @param clas * @param constructor * @param args * @return
*/
public static Object instanceCreate(Class<?> clas,Constructor<?> constructor,Object[] args) { /** * Enhancer允许为非接口类型创建一个Java代理。Enhancer动态创建了给定类型的子类但是拦截了所有的方法。和Proxy不一样的是,不管是接口还是类他都能正常工作 */ Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(clas);//代理类
enhancer.setCallback(NoOp.INSTANCE);//代理类型>初始化实例
if(null == constructor) { return enhancer.create();//默认创建无参数实例
}else { return enhancer.create(constructor.getParameterTypes(),args);//带参数的初始化
} } }
类装载工具类:
package light.zhang.ioc.utils; /** * 主要负责读取配置文件,装载类信息 * @author witts * */
public class ClassLoaderUtils { /**创建读取配置信息的对象**/
public static ClassLoader install() { return Thread.currentThread().getContextClassLoader(); } /**装载class**/
public static Class<?> loaderClass(String className) { try { return install().loadClass(className);//通过配置文件装载类信息
}catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } }
json工具类:
package light.zhang.ioc.utils; import java.io.InputStream; import java.text.SimpleDateFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; public class JsonUtils { private static final ObjectMapper mapper = new ObjectMapper(); private JsonUtils() { } public static ObjectMapper getObjectMapper() { return mapper; } public static <T> T readValue(String json, Class<T> cls) { try { return mapper.readValue(json, cls); } catch (Exception var3) { return null; } } public static <T> T readValue(InputStream is,Class<T> cls){ try{ return mapper.readValue(is,cls); }catch (Exception e){ return null; } } public static <T> T readValue(byte[] bytes, Class<T> cls) { try { return mapper.readValue(bytes, cls); } catch (Exception var3) { return null; } } public static <T> T readValue(String json, TypeReference<?> valueTypeRef) { try { return mapper.readValue(json, valueTypeRef); } catch (Exception var3) { return null; } } public static <T> T readValue(byte[] bytes, TypeReference<?> valueTypeRef) { try { return mapper.readValue(bytes, valueTypeRef); } catch (Exception var3) { return null; } } public static <T> T readValue(InputStream is,TypeReference<?> valueTypeRef){ try{ return mapper.readValue(is,valueTypeRef); }catch (Exception e){ return null; } } public static String writeValue(Object entity) { try { return mapper.writeValueAsString(entity); } catch (Exception var2) { return null; } } public static byte[] writeByteValue(Object entity) { try { return mapper.writeValueAsBytes(entity); } catch (Exception var2) { return null; } } static { mapper.enable(SerializationFeature.INDENT_OUTPUT); mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); mapper.setSerializationInclusion(JsonInclude.Include.USE_DEFAULTS); mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); mapper.getDeserializationConfig().withoutFeatures(new DeserializationFeature[]{DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES}); mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, true); mapper.configure(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING,true); mapper.configure(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS, true); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } }
反射类:
package light.zhang.ioc.utils; import java.lang.reflect.Field; /** * 主要通过 Java 的反射原理来完成对象的信息注入 * @author witts */
public class ReflectionUtils { /** * 初始化参数信息 * @param field * @param key * @param val * @throws IllegalAccessException */
public static void initParamter(Field field,Object key,Object val) throws IllegalAccessException { if(null !=field) { field.setAccessible(Boolean.TRUE); field.set(key, val);//注入参数信息
} } }
客户端调用
package light.zhang.ioc.test; import junit.framework.TestCase; import light.zhang.ioc.client.JsonApplicationContext; import light.zhang.ioc.core.ApplicationContext; /** * 模拟spring ioc对象创建管理销毁 * @author witts * */
public class AppTest extends TestCase { private static final ApplicationContext applicationContext=new JsonApplicationContext("application.json"); //读取配置文件
public static void main(String[] args) { try { Robot aiRobot; aiRobot = (Robot) applicationContext.getBean("robot");//获取对象
aiRobot.show();//调用对象功能
} catch (Exception e) { e.printStackTrace(); } } }
需要被管理的对象
package light.zhang.ioc.test; public class Hand { public void waveHand(){ System.out.println("hand out message"); } }
package light.zhang.ioc.test; public class Mouth { public void speak(){ System.out.println("Mouth out message"); } }
package light.zhang.ioc.test; public class Robot { //需要注入 hand 和 mouth,容器自动注入对象并实例化
private Hand hand; private Mouth mouth; public void show(){ hand.waveHand(); mouth.speak(); } }
主要是理解spring ioc的加载-实例-注册-销毁等一系列的对象生命周期管理,我这里只是模仿一下spring对对象的加载,创建,注册 对象销毁是个复杂的过程,并不是那么容器就模拟出来的,
spring管理的对象方式有很多种,
本来是由应用程序管理的对象之间的依赖关系,现在交给容器管理,这就是控制反转,及交给Ioc容器。Spring的IoC主要使用DI方式实现,
不需要主动查找,对象的查找、定位和创建全部由容器管理。spring中有三种注入方式,一种是set注入,一种是接口注入,另一种是构造方法注入