手写Spring mvc框架 (二)
五、控制反转(IOC)和依赖注入(DI)
-
概念
-
控制反转:将创建对象的控制权反转给了spring
-
依赖注入:spring在创建对象的过程中,动态地将依赖对象注入到Bean组件
-
-
实现
工厂模式-BeanFactory
从BeanFactory中获取对象,没有就创建,依赖没有就创建依赖,对象一般默认单例模式
递归创建依赖会遇到循环依赖问题:
- 如果需要的依赖正处于创建状态,则发生了循环依赖(可用ConcurrentHashMap缓存对象来判断)
- 处理:将那个依赖的初始状态对象注入,即那个依赖对象里的成员变量为null
BeanFactory简易实现代码:
public class BeanFactory { //一个类对应一个对象 private static Map<Class<?>, Object> classToBean = new ConcurrentHashMap<>(); public static Object getBean(Class<?> cls) { return classToBean.get(cls); } public static void initBean(List<Class<?>> classList) throws Exception { List<Class<?>> toCreate = new ArrayList<>(classList); while (toCreate.size() != 0) { int remainSize = toCreate.size(); for (int i=0;i<toCreate.size();i++) { if (finishCreate(toCreate.get(i))) { toCreate.remove(i); } } if (toCreate.size() == remainSize) { //这里没有解决循环依赖 throw new Exception("cycle dependency!"); } } } private static boolean finishCreate(Class<?> cls) throws IllegalAccessException, InstantiationException { if (!cls.isAnnotationPresent(Bean.class) && !cls.isAnnotationPresent(Controller.class)) { return true; } Object bean = cls.newInstance(); for (Field field : cls.getDeclaredFields()) { if (field.isAnnotationPresent(AutoWired.class)) { Class<?> fieldType = field.getType(); Object reliantBean = BeanFactory.getBean(fieldType); if (reliantBean == null) { return false; } field.setAccessible(true); field.set(bean, reliantBean); } } classToBean.put(cls, bean); return true; } }
六、AOP
概念:弥补OOP的缺点,给每个函数前后留一个切面,可以实现业务代码和功能代码的分离
-
jdk代理
被代理对象需要有个接口,jdk通过动态实现这个接口来实现代理
-
cgLib代理
被代理对象没有接口怎么办?我们通过获取它的class字节码文件,创造一个继承它的子类,从而实现代理