纯手写轻量级springioc aop

本文介绍了作者在GitHub上的一个开源项目,详细阐述了如何纯手写实现一个轻量级的Spring IOC和AOP。通过扫描指定包下的类,识别并收集带有注解的bean,然后将这些bean存入容器。接着,检查每个bean的属性,如果发现需要注入的依赖,便从容器中找到对应的bean进行注入。最后,利用CGLIB对所有bean进行动态代理,实现AOP的功能。注释清晰,对于理解源码有很大帮助。
摘要由CSDN通过智能技术生成

 

github地址:https://github.com/919337588/cxaopioc

大致目录结构如此

注释算是非常清晰,比直接看源码容易理解的多 我写的是注解版

大致逻辑就是 

1扫描包下的类

2如果类存在注入bean所需的注解 将bean放入bean容器

3查看beanA中的属性 如果属性需要注入 就在bean容器中找到对应的beanB 并且注入到beanA的属性中

4 使用cglib动态代理所有的bean 达到aop效果

ClassUtil是网址寻找的反射工具类
package com.chixin.spring;

import com.chixin.note.CxAutowired;
import com.chixin.note.CxCompent;
import com.chixin.note.CxControl;
import com.chixin.note.CxService;
import com.chixin.utils.ClassUtil;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ApplicationContext {
    /*扫包地址*/
    private String packagePath;
    //bean容器
    private ConcurrentHashMap<Class,Object> beanfactory;
    /*bean注释集合*/
    private static HashSet<Class> containerAnnotations;

    static {
        //初始化bean的注入注解
        containerAnnotations=new HashSet<Class>();
        containerAnnotations.add(CxControl.class);
        containerAnnotations.add(CxService.class);
        containerAnnotations.add(CxCompent.class);
    }
    public ApplicationContext(String packagePath) throws Exception {
        this.packagePath=packagePath;
        beanfactory = new ConcurrentHashMap<Class, Object>();
        //初始化bean
        initBeans();
        //完善bean
        beanDecoration();
    }
  // 初始化bean对象
    public void initBeans() throws Exception {
        List<Class> listClassesAnnotation= findClassExisService();
        for (Class classInfo : listClassesAnnotation) {
            // 初始化对象
            Object newInstance =classInfo.newInstance();
            // bean放入容器
            beanfactory.put(classInfo, newInstance);
        }
    }
    //完善bean
    public void beanDecoration() throws Exception {
        for(Map.Entry<Class,Object> val: beanfactory.entrySet()){
            //给bean的属性注入值
            attriAssign(val.getValue());
            //aop包裹
            doAop(val);
        };
    }
    // 使用反射读取类的属性,赋值信息
    public void attriAssign(Object object) throws Exception {
        // 1.获取类的属性是否存在 获取bean注解
        Class<? extends Object> classInfo = object.getClass();
        Field[] declaredFields = classInfo.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.getDeclaredAnnotation(CxAutowired.class) != null) {
                Object bean = beanfactory.get(field.getType());
                if (bean != null) {
                    // 私有访问允许访问
                    field.setAccessible(true);
                    // 给属性赋值
                    field.set(object, bean);
                }
            }
        }
    }
    // bean变为aop代理对象
    public void doAop(Map.Entry<Class,Object> val ) throws Exception {
        val.setValue(CglibProxy.initAop(val.getValue()));
    }

    // 使用反射机制获取该包下所有的类已经存在bean的注解类
    public List<Class> findClassExisService() throws Exception {
        // 1.使用反射机制获取该包下所有的类
        if (StringUtils.isBlank(packagePath)) {
            throw new Exception("扫包地址不能为空!");
        }
        // 2.使用反射技术获取当前包下所有的类
        List<Class<?>> classesByPackageName = ClassUtil.getClasses(packagePath);
        // 3.存放类上有bean注入注解
        List<Class> exisClassesAnnotation = new LinkedList<>();
        // 4.判断该类上属否存在注解
        for (Class classInfo : classesByPackageName) {
            for (Class containerAnnotation:containerAnnotations){
                Object cx =  classInfo.getDeclaredAnnotation(containerAnnotation);
                if (cx != null) {
                    exisClassesAnnotation.add(classInfo);
                    break;
                }
            }
        }
        return exisClassesAnnotation;
    }
    public <T>T getBean(Class classinfo){
        return (T) beanfactory.get(classinfo);
    }
}
package com.chixin.spring;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class CglibProxy implements MethodInterceptor {
    private Object tar;
    CglibProxy(Object tar){
        this.tar=tar;
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result = null;
       try {
           System.out.println("----------------------------------"+method.getDeclaringClass().getName()+" "+method.getName()+" aop前置捕捉");
           result = methodProxy.invoke(tar, objects);
           System.out.println("----------------------------------"+method.getDeclaringClass().getName()+" "+method.getName()+" aop后置捕捉");
       }catch (Exception e){
           System.out.println("----------------------------------"+method.getDeclaringClass().getName()+" "+method.getName()+" aop异常捕捉");
       }
        return result;
    }
    public static Object initAop(Object classInfo) throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(classInfo.getClass());
        enhancer.setCallback(new CglibProxy(classInfo));
        return enhancer.create();
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值