手写spring框架:实现ioc和aop功能;使用三级缓存解决循环依赖问题

1.项目架构:

本文只提供重点代码,具体实现请参考文末源码。

采用三级缓存解决循环依赖,原理参考 手写spring框架预备知识:三级缓存解决循环依赖问题

2. 启动类

        在main函数中注册自己,并添加ComponentScan注解

@ComponentScan
public class SpringApplication {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ApplicationContext(SpringApplication.class);

    }
}

 3.封装bean信息

        需要封装的bean类型

    //注册配置信息
    private Class<?> configClazz;
    /**
     * 注册配置类解析器
     */
    private BeanDefinitionReader reader;
    /**
     * 存放所有的bean对象原始信息
     */
    private Map<String, BeanDefinition> beanDefinitionMap;

    /**
     * 存放beanPostProcessor集合,自定义bean的前后处理逻辑
     */
    private CopyOnWriteArrayList<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
    /**
     * 存放aopProcessor集合,自定义切面逻辑
     */
    private CopyOnWriteArrayList<AopProcessor> aopProcessors = new CopyOnWriteArrayList<>();

    /**
     * 一级缓存,存放经过完整生命周期的单例bean对象
     */
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();

    /**
     * 二级缓存,存放提前进行aop代理的bean对象
     */
    private ConcurrentHashMap<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
    /**
     * 三级缓存,存放构造器创建的原始bean对象
     */
    private ConcurrentHashMap<String, Object> singletonFactories = new ConcurrentHashMap<>();
    /**
     * 记录正在创建中的bean,用于判断是否出现循环依赖
     */
    private Set<String> creatingSet = Collections.newSetFromMap(new ConcurrentHashMap<>());

         完成具体的封装操作

public ApplicationContext(Class<?> configClazz) {
        this.configClazz = configClazz;
        //初始化spring容器
        refresh();
    }

    public void refresh() {
        //解析配置文件扫描路径
        reader = new BeanDefinitionReader(configClazz);
        //封装class文件为beanDefinition对象
        beanDefinitionMap = reader.loadBeanDefinitions();
//        System.out.println("beanDefinitionMap = " + beanDefinitionMap);
//        注册所有的BeanPostProcessor,需要提前创建对象
        loadBeanPostProcessors();
//        System.out.println("beanPostProcessors = " + beanPostProcessors);
        //注册所有的AopProcessor,需要提前创建对象
        loadAopProcessor();
//        System.out.println("aopProcessors = " + aopProcessors);
        //提前创建所有的bean对象
        doCreate();
        
    }

3.创建bean对象

        一个完整的生命周期需要经过构造器创建→依赖注入→Aop处理 

private void doCreate() {
        for (String beanName : beanDefinitionMap.keySet()) {
            createBean(beanDefinitionMap.get(beanName));
        }
    }
 /**
     * 核心功能,根据beanDefinition创建对应的对象
     *
     * @param beanDefinition
     * @return 创建后的对象
     */
    private Object createBean(BeanDefinition beanDefinition) {
        Class<?> clazz = beanDefinition.getClazz();
        String beanName = beanDefinition.getBeanName();
        //如果已经被提前创建则直接返回
        if (singletonObjects.containsKey(beanName)) {
            return singletonObjects.get(beanName);
        }
        Object instance = null;
        try {
            //1.构造器创建原始bean
            instance = clazz.getDeclaredConstructor().newInstance();
            //放入creatingSet和三级缓存中
            singletonFactories.put(beanName, instance);
            creatingSet.add(beanName);
            //2.如果不是懒加载则执行依赖注入
            if (!beanDefinition.isLazy()) {
                dependencyInjection(clazz, instance);
            }
            //3.进行Aop
            //先判断是否已经提前aop过
            if (earlySingletonObjects.containsKey(beanName)) {
                instance = earlySingletonObjects.get(beanName);
            } else {
                instance = createBeanAfterDI(beanDefinition);
            }
            //4.放入单例池并清空二级缓存
            singletonObjects.put(beanName, instance);
            earlySingletonObjects.remove(beanName);
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                 NoSuchMethodException e) {
            throw new RuntimeException("创建" + beanName + "对象失败");
        }
        return instance;
    }

3.1 依赖注入

        未出现循环依赖则递归创建对象,出现循环依赖则提前进行Aop创建对象,这里是解决循环依赖的关键。

private void dependencyInjection(Class<?> clazz, Object instance) {
        for (Field declaredField : clazz.getDeclaredFields()) {
            //属性上有依赖注入的注解
            if (declaredField.isAnnotationPresent(AutoWired.class)) {
                String fieldBeanName = BeanUtils.getDefaultBeanName(declaredField.getType());
//                System.out.println("fieldBeanName = " + fieldBeanName);
                AutoWired autoWired = declaredField.getAnnotation(AutoWired.class);
                BeanDefinition fieldBeanDefinition = beanDefinitionMap.get(fieldBeanName);
                declaredField.setAccessible(true);
                try {
                    if (singletonObjects.containsKey(fieldBeanName)) {
                        //从单例池中寻找注入的对象
                        declaredField.set(instance, singletonObjects.get(fieldBeanName));
                    } else if (earlySingletonObjects.containsKey(fieldBeanName)) {
                        //从二级缓存中寻找注入的对象
                        declaredField.set(instance, earlySingletonObjects.get(fieldBeanName));
                    } else {
                        //创建新对象
                        //判断该对象是否正在创建
                        if (!creatingSet.contains(fieldBeanName)) {
                            //没有循环依赖则直接创建对象
                            Object bean = createBean(fieldBeanDefinition);
                            declaredField.set(instance, bean);
                        } else {
                            //出现循环依赖则提前进行aop创建对象
                            Object earlyBean = createBeanAfterDI(fieldBeanDefinition);
                            declaredField.set(instance, earlyBean);
                        }
                    }
                } catch (IllegalAccessException e) {
                    if (autoWired.require()) {
                        throw new RuntimeException("给" + clazz.getSimpleName() + "注入" + fieldBeanName + "失败");
                    }
                }
            }
        }
    }

3.2 Aop动态代理 

        有接口则用jdk动态代理,否则使用cjlib动态代理,此处是创建bean的最后一步,是执行扩展功能的地方,Aop本质上其实也是一种扩展功能。

private Object createBeanAfterDI(BeanDefinition beanDefinition) {
        String beanName = beanDefinition.getBeanName();
        Class<?> clazz = beanDefinition.getClazz();
        try {
            //从三级缓存中获取原始bean对象
            Object bean = singletonFactories.get(beanName);
            //执行bean初始化前逻辑
            for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
                beanPostProcessor.postProcessBeforeInitialization(bean, beanName);
            }
            //执行自定义初始化
            if (InitializingBean.class.isAssignableFrom(clazz)) {
                InitializingBean initializingBean = (InitializingBean) bean;
                initializingBean.afterPropertiesSet();
            }
            //执行bean初始化前的逻辑
            for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
                beanPostProcessor.postProcessAfterInitialization(bean, beanName);
            }
            //-------------------------AOP入口-----------------------
            for (AopProcessor aopProcessor : aopProcessors) {
                String pointCut = aopProcessor.getPointCut();
                if (BeanUtils.aopMatch(pointCut, clazz.getName())) {
                    //匹配到切面,则创建代理对象执行切面逻辑
                    if (clazz.getInterfaces().length > 0) {
                        //如果有接口,使用jdk动态代理
                        JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy(bean, aopProcessor);
                        bean = jdkDynamicProxy.getProxyBean();
                    } else {
                        //没有接口用cglib
                        CglibProxy cglibProxy = new CglibProxy(bean, aopProcessor);
                        bean = cglibProxy.getProxyBean();
                    }
                }
            }
            //向二级缓存添加bean对象
            earlySingletonObjects.put(beanName, bean);
            //删除三级缓存的bean对象和creatingSet
            singletonFactories.remove(beanName);
            creatingSet.remove(beanName);
            return bean;
        } catch (Exception e) {
            throw new RuntimeException(beanName + "的Aop处理失败");
        }
    }

4.结果测试

        该部分进行结果的测试,测试spring容器的ioc和aop功能以及循环依赖的问题。测试结构如下;

User类

@Component
@Scope("prototype")//测试循环依赖的时候需要取消注释
public class UserImpl implements User {
    @AutoWired
    private CglibTest cglibTest;

    public void print(){
        System.out.println("User中注入了:" + cglibTest);
    }
}

 UserService类

@Service
public class UserServiceImpl implements UserService {
    @AutoWired
    private User user;

    public void print(){
        System.out.println("userService中注入了:" + user);
        user.print();
    }
}

 CglibTest类

@Component
public class CglibTest {
    @AutoWired
    private UserService userService;
    public void print() {
        System.out.println("cglibTest中注入了:" + userService);
        userService.print();
    }
}

4.1 测试ioc容器(未开启Aop和功能扩展类)

        启动类

@ComponentScan
public class SpringApplication {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ApplicationContext(SpringApplication.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanName : beanDefinitionNames) {
            System.out.println("beanName = " + beanName);
            Object bean1 = applicationContext.getBean(beanName);
            Object bean2 = applicationContext.getBean(beanName);
            System.out.println("bean1 = " + bean1);
            System.out.println("bean2 = " + bean2);
            System.out.println("-----------------------------");
        }

//        System.out.println("循环依赖测试开始*******************************");
//        CglibTest cglibTest = (CglibTest) applicationContext.getBean("cglibTest");
//        cglibTest.print();
//        System.out.println("循环依赖测试结束*******************************");
    }
}

        结果: 

         分析:结果中可以看到所有的bean都被注册进单例池中,但是User类由于指定了属性为原型类,所以两次获得的bean对象并不相同,并且缓存中只有一级缓存中还有对象,其余缓存均已清空。

4.2 测试Aop和循环依赖

        添加aop类和扩展类,只给impl包下的对象执行aop操作

@Component
@Aspect
public class AopTest {
    @PointCut("spring.test.impl.*")
    public void pointcut(){}

    @Before
    public void before(ProceedingJoinPoint joinPoint) {
        String beanName = joinPoint.getBeanName();
        System.out.println(beanName + "aop方法执行前");
    }

    @After
    public void after(ProceedingJoinPoint joinPoint){
        String beanName = joinPoint.getBeanName();
        System.out.println(beanName + "aop方法执行后");
    }
}
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println(beanName + "初始化前");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println(beanName + "初始化后");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

        启动类:

@ComponentScan
public class SpringApplication {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ApplicationContext(SpringApplication.class);
//        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
//        for (String beanName : beanDefinitionNames) {
//            System.out.println("beanName = " + beanName);
//            Object bean1 = applicationContext.getBean(beanName);
//            Object bean2 = applicationContext.getBean(beanName);
//            System.out.println("bean1 = " + bean1);
//            System.out.println("bean2 = " + bean2);
//            System.out.println("-----------------------------");
//        }

        System.out.println("循环依赖测试开始*******************************");
        CglibTest cglibTest = (CglibTest) applicationContext.getBean("cglibTest");
        cglibTest.print();
        System.out.println("循环依赖测试结束*******************************");
    }
}

        结果:

 

         分析:所有对象在初始化前后都执行了我们自定义的扩展功能,并且每个impl包下的方法在执行前后都会执行自定义aop逻辑。而从打印结果中来看,即使出现循环依赖现象,每一个bean对象都能成功的注入想要的属性,并且初始化顺序也符合最开始的创建逻辑,即A要注入B,B要注入C,C要注入A,判断A和C出现循环依赖,则需要提前创建A,然而B和C没有出现循环依赖,则先创建C,再创建B。其中A对应CglibTest,B对应UserService,C对应User。

5.项目地址

  手写spring框架

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值