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注入,一种是接口注入,另一种是构造方法注入