獻(xiàn)上一段自己寫的極其簡陋版的ioc容器的實(shí)現(xiàn)吮螺,幫助大家了解spring基本原理
步驟:
1、首先自定義注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAutowired {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponent {
}
然后創(chuàng)建緩存(我這里只有兩個(gè)個(gè)緩存)牵敷,兩個(gè)緩存主要起到單例和解決循環(huán)依賴的作用虽界,一級(jí)緩存主要存放已經(jīng)創(chuàng)建好并且已經(jīng)完全屬性賦值好的bean,二級(jí)緩存主要存放實(shí)例化但是未屬性賦值的bean,注意:這里一級(jí)緩存和二級(jí)緩存相同beanName存放的bean都是指向同一個(gè)內(nèi)存地址炫加,只是bean沒完成創(chuàng)建好時(shí)暫時(shí)存放在二級(jí)緩存中
public final static Map<String, Object> oneCache = new ConcurrentHashMap<>();
public final static Map<String, Object> twoCache = new ConcurrentHashMap<>();
下面是兩個(gè)用來測試的bean,并且相互注入
@MyComponent
@Setter
@Getter
public class Cat {
@MyAutowired
private Dog dog;
}
@MyComponent
@Setter
@Getter
public class Dog {
@MyAutowired
private Cat cat;
private String name;
private int age;
public Dog() {
this.name="dog";
this.age=10;
}
@Override
public String toString() {
return "Dog{" +
"cat=" + cat +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
下面是我自己實(shí)現(xiàn)的getBean窟哺,已經(jīng)解決循環(huán)依賴問題泻轰,代碼不難,主要是使用一級(jí)緩存和二級(jí)緩存處理單例和循環(huán)依賴問題且轨,然后利用反射實(shí)現(xiàn)bean的創(chuàng)建及屬性的賦值
public class MyGetBean {
public final static Map<String, Object> oneCache = new ConcurrentHashMap<>();
public final static Map<String, Object> twoCache = new ConcurrentHashMap<>();
public Object getBean(Class clazz) throws Exception {
if (clazz.isAnnotationPresent(MyComponent.class)) {
String simpleName = clazz.getSimpleName();
StringBuilder beanName = new StringBuilder(simpleName);
beanName.replace(0, 1, simpleName.substring(0, 1).toLowerCase());
Object bean = getSingleton(beanName.toString());
if (bean != null) {
return bean;
}
bean = createBean(clazz, beanName.toString());
return bean;
} else {
throw new RuntimeException("容器沒找到該類型的bean");
}
}
private Object getSingleton(String beanName) {
Object one = oneCache.get(beanName);
if (one == null) {
one = twoCache.get(beanName);
} else {
twoCache.remove(beanName);
}
return one;
}
private synchronized Object createBean(Class clazz, String beanName) throws Exception {
Object bean = oneCache.get(beanName);
if (bean == null) {
bean = clazz.newInstance();
twoCache.put(beanName, bean);
for (Field field : clazz.getDeclaredFields()) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
if (field.isAnnotationPresent(MyAutowired.class)) {
Class<?> type = field.getType();
Object inject = getBean(type);
field.set(bean, inject);
}
}
oneCache.put(beanName, bean);
}
return bean;
}
}
測試浮声,運(yùn)行無錯(cuò)誤
public class Test {
@org.junit.Test
public void test() throws Exception {
MyGetBean myGetBean = new MyGetBean();
Cat bean = (Cat) myGetBean.getBean(Cat.class);
System.out.println(bean.getDog().toString());
}
}