一、IOC定义
控制反转(Inversion of Control,英文缩写为IoC)。
定义很难理解,下面说下我个人的理解:
1、控制,即对象创建的控制,Java是面向对象的语言,传统的创建对象都是手动new一个对象,是由程序员自己控制的。
2、反转则是把创建对象的过程交给容器去创建。
二、思路
既然是把创建对象交给容器去创建,那么首先我们必须要知道我们对哪些类创建对象交给容器去管理。
所以就有以下类:
①、自定义IOC注解,只有注解的才能被容器管理
②、要被容器管理的对象那些类
③、容器类,管理对象
④、容器工厂类
⑤、创建对象的类,把创建好的对象交给容器管理
⑥、扫描类,只有被扫描到的类才能被容器管理
⑦、测试类
三、源码实现
1、注解Ioc类
import java.lang.annotation.*;
/**
* @Author: liudq
* @Description: 自定义IOC注解
* @Date: create in 2017/10/29 14:22
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE})
public @interface Ioc {
boolean isCreate() default true;
}
2、被管理对象的类
①、学生类
/**
* @Author: liudq
* @Description: 学生
* @Date: create in 2017/10/29 14:22
*/
@Ioc
public class Student {
private long id;
private String name;
private int age;
private boolean sex;
@Ioc
private Address address;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
②、地址类
/**
* @Author: liudq
* @Description: 地址类
* @Date: create in 2017/10/29 14:22
*/
@Ioc
public class Address {
private long id;
@Ioc
private Province province;
@Ioc
private City city;
private String detail;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Province getProvince() {
return province;
}
public void setProvince(Province province) {
this.province = province;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
}
③、省类
/**
* @Author: liudq
* @Description: 省
* @Date: create in 2017/10/29 14:22
*/
@Ioc
public class Province {
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
④、市类
/**
* @Author: liudq
* @Description: 市
* @Date: create in 2017/10/29 14:22
*/
@Ioc
public class City {
private long id;
private String name;
@Ioc
private Province province;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Province getProvince() {
return province;
}
public void setProvince(Province province) {
this.province = province;
}
}
3、容器类
/**
* @Author: liudq
* @Description: Bean容器
* @Date: create in 2017/10/29 14:22
*/
public interface BeanContext {
T getBean(String name) throws Exception;
T getBean(Class clz);
void addBean(Class clz);
void addBean(String clz);
}
import java.util.HashMap;
import java.util.Map;
/**
* @Author: liudq
* @Description: 默认Bean容器类
* @Date: create in 2017/10/29 14:22
*/
public class DefaultBeanContext implements BeanContext {
private Map context = new HashMap();
private Bean instance = new Bean();
@Override
public T getBean(String name) {
name = analysisName(name);
return (T) context.get(name);
}
@Override
public T getBean(Class clz) {
return getBean(clz.getName());
}
@Override
public void addBean(Class clz) {
addBean(clz.getName());
}
@Override
public void addBean(String name) {
String key = analysisName(name);
Object bean = context.get(key);
if (bean == null){
bean = instance.createObject(name);
context.put(key,bean);
}
}
public static String analysisName(String name){
if (name == null || "".equals(name)){
throw new NullPointerException("类名称不能为空!");
}
String[] split = name.split("\\.");
if (split != null && split.length > 0){
String s = split[split.length - 1];
String first = s.substring(0,1).toLowerCase();
String end = s.substring(1,s.length());
return first+end;
}
String first = name.substring(0,1).toLowerCase();
String end = name.substring(1,name.length());
return first+end;
}
}
4、容器工厂类
/**
* @Author: liudq
* @Description: Bean容器工厂类
* @Date: create in 2017/10/29 14:22
*/
public class BeanContextFactory {
private static BeanContext beanContext = new DefaultBeanContext();
public static BeanContext createBeanContext(){
return beanContext;
}
}
5、创建对象的类
import java.lang.reflect.Constructor;
import java.util.*;
/**
* @Author: liudq
* @Description: 创建bean
* @Date: create in 2017/10/29 14:22
*/
public class Bean {
public T createObject(Class clz){
return createObject(clz,null,null);
}
public T createObject(Class clz, List> constructTypes, List constructArgs){
Class> aClass = resolveInterface(clz);
return (T)instance(aClass, constructTypes, constructArgs);
}
public Object createObject(String name) {
Object o = null;
try {
Class> aClass = Class.forName(name);
o = aClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
protected T instance(Class clz, List> constructTypes, List constructArgs) {
try {
Constructor constructor;
if (constructTypes == null || constructArgs == null){
constructor = clz.getDeclaredConstructor();
return constructor.newInstance();
}
constructor = clz.getDeclaredConstructor(constructTypes.toArray(new Class[constructArgs.size()]));
return constructor.newInstance(constructArgs.toArray(new Object[constructArgs.size()]));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("创建对象异常");
}
}
protected Class> resolveInterface(Class> type) {
Class> classToCreate;
if (type == List.class || type == Collection.class || type == Iterable.class) {
classToCreate = ArrayList.class;
} else if (type == Map.class) {
classToCreate = HashMap.class;
} else if (type == SortedSet.class) {
classToCreate = TreeSet.class;
} else if (type == Set.class) {
classToCreate = HashSet.class;
} else {
classToCreate = type;
}
return classToCreate;
}
}
6、扫描类
import java.lang.reflect.Field;
/**
* @Author: liudq
* @Description: 扫描Bean
* @Date: create in 2017/10/29 14:22
*/
public class Scan {
private BeanContext beanContext;
public Scan(BeanContext beanContext){
this.beanContext = beanContext;
}
public BeanContext getBeanContext() {
return beanContext;
}
public void setBeanContext(BeanContext beanContext) {
this.beanContext = beanContext;
}
public void scan(Class> clz ){
scan(new Class[]{clz});
}
public void scan(Class>[] clzs){
for (Class clz : clzs){
Ioc ioc = (Ioc) clz.getAnnotation(Ioc.class);
if (ioc != null){
if (ioc.isCreate()){
beanContext.addBean(clz);
System.out.println("类"+clz.getName()+" 被注册");
}
}
Field[] declaredFields = clz.getDeclaredFields();
if (declaredFields != null){
for (Field field : declaredFields){
Ioc annotation = field.getAnnotation(Ioc.class);
if (annotation != null){
if (annotation.isCreate()){
Class> fieldType = field.getType();
beanContext.addBean(fieldType);
System.out.println(clz.getName()+"里的"+field.getName()+"字段的类型"+fieldType.getName()+" 被注册");
try {
field.setAccessible(true);
field.set(beanContext.getBean(clz),beanContext.getBean(fieldType));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
7、测试类
/**
* @Author: liudq
* @Description: 测试
* @Date: create in 2017/10/29 14:22
*/
public class App {
public static void main(String[] args) {
BeanContext beanContext = BeanContextFactory.createBeanContext();
Scan scan = new Scan(beanContext);
scan.scan(new Class[]{Student.class,Address.class,Province.class,City.class});
Student student = beanContext.getBean(Student.class);
System.out.println(student.getAddress().getProvince().getName());
}
}
四、目的
IOC的主要目的是解耦合。
五、浅谈
这里只是一个简单的IOC的实现,主要技术是Java的反射。希望有助于大家对IOC的理解。
实践是检验真理的唯一标准。只有我们自己多敲代码多测试才能加深我们对程序的理解。