手写Spring框架源码(基础款)(AOP JDK动态代理)

本文详细介绍了如何在Spring框架中利用AOP进行类的自定义逻辑扩展,涉及接口定义、JDK动态代理和后置处理器的使用,通过实例演示了如何在初始化后替换类的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原生的Spring框架除了IOC还有个强大的功能---AOP

之所以出现AOP,对原本的类没有任何侵入性的情况下还可以对它进行自定义逻辑。

首先要明白AOP在Spring的生命周期里的哪一步去做的,做了什么。

生命周期里的哪一步去做的:时间点是初始化后做的。

做了什么:生成一个代理类,把这个代理类放到容器里替你做事。

此处是用JDK的动态代理(JDK的动态代理有一个特点就是这个被代理的对象必须实现一个接口才能给这个对象生成代理对象

第一步:写一个接口让类重写接口方法

public interface YuWenWenServiceIfa {

    void test();
}
@Component("yuWenWenService")
public class YuWenWenService implements YuWenWenServiceIfa {


    @Autowired
    private MiaoWenWenService miaoWenWenService;

    public String beanName;


    public void test() {
        System.out.println(miaoWenWenService);
        System.out.println(beanName);
    }
}

第二步:JDK生成动态代理对象(此处也可用Cglib动态代理)

Proxy.newProxyInstance方法参数一共有三个,类加载器,接口,invocationHandler

其中invocationHandler是一个函数式接口(既然是函数式接口就可以Lamda)

Proxy.newProxyInstance(YuWenWenApplicationContext.class.getClassLoader(), bean.getClass().getInterfaces(),
                    (Object p, Method m, Object[] a) -> {
                        System.out.println("代理逻辑前");
                        Object c=m.invoke(bean,a);
                        System.out.println("代理逻辑前");
                        return c;
                    });

第三步:在初始化后做动态代理逻辑

    @Override
    public Object postProcessAfterInitialization(Object bean) {
        System.out.println("后置处理器,初始化后");
        if (bean.getClass() == YuWenWenService.class) {
            Object proxy = Proxy
                .newProxyInstance(YuWenWenApplicationContext.class.getClassLoader(), bean.getClass().getInterfaces(),
                    (Object p, Method m, Object[] a) -> {
                        System.out.println("代理逻辑前");
                        Object c=m.invoke(bean,a);
                        System.out.println("代理逻辑后");
                        return c;
                    });
            return proxy;
        }
        return bean;
    }

测试:注意一下,因为容器里面不是YuWenWenService这个对象了 而是他的代理对象YuWenWenServiceIfa

public class ApplicationTest {


    public static void main(String[] args)
        throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        YuWenWenApplicationContext yuWenWenApplicationContext = new YuWenWenApplicationContext(AppConfig.class);
        YuWenWenServiceIfa yuWenWenService = (YuWenWenServiceIfa) yuWenWenApplicationContext.getBean("yuWenWenService");
        yuWenWenService.test();
    }
}

成功 

代理逻辑前
com.sbi.service.MiaoWenWenService@3b764bce
null
代理逻辑后

 源码奉上

package com.sbi.config;

import com.sbi.annotation.Autowired;
import com.sbi.annotation.Component;
import com.sbi.annotation.ComponentScan;
import com.sbi.annotation.Scope;
import com.sbi.service.BeanPostProcessor;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class YuWenWenApplicationContext {

    private Class config;

    // 单例池(key:beanName,value:bean)
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
    // BeanDefinitionMap(key:beanName,value:类描述)
    private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    // BeanPostProcessorList
    private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    public YuWenWenApplicationContext(Class config)
        throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        this.config = config;
        // 扫描bean,并且得到所有beanDefinition放在beanDefinitionMap里
        scan(config);
        // 循环beanDefinitionMap全部
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            if (entry.getValue().getScope().equals("singleton")) {
                // 创建bean
                Object bean = createBean(entry.getValue());
                // 将创建好的bean放到单例池等待getBean调用
                singletonObjects.put(entry.getKey(), bean);
            }
        }
    }

    private Object createBean(BeanDefinition beanDefinition)
        throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 第一步:创建对象
        Object o = beanDefinition.getClazz().getDeclaredConstructor().newInstance();
        // 第二部:依赖注入
        // 先通过反射拿到这个对象的私有属性
        Field[] declaredFields = o.getClass().getDeclaredFields();
        // 遍历私有属性
        for (Field field : declaredFields) {
            // 判断私有属性的是否持有@Autowired
            if (field.isAnnotationPresent(Autowired.class)) {
                // 如果持有@Autowired 就从单例池里拿这个bean并赋值
                Object bean = getBean(field.getName());

                // 默认是不允许设置私有属性的值的 此处必须得改成true
                field.setAccessible(true);
                // 实现依赖注入
                field.set(o, bean);

            }
        }
        // 第三步:Aware回调以及初始化方法
        if (o instanceof BeanNameAware) {
            ((BeanNameAware) o).setBeanName();
        }

        // 第四步:BeanPostProcessor的前置方法
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            o = beanPostProcessor.postProcessBeforeInitialization(o);

        }
        // 第五步:初始化方法
        if (o instanceof InitializingBean) {
            ((InitializingBean) o).afterPropertiesSet();
        }
        // 第六步:BeanPostProcessor的后置方法
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            o = beanPostProcessor.postProcessAfterInitialization(o);
        }
        return o;
    }

    private void scan(Class config)
        throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 此处得到@ComponentScan的扫描路径
        ComponentScan path = (ComponentScan) config.getDeclaredAnnotation(ComponentScan.class);
        // 得到一个类加载器 classpath下面用AppClassLoader
        ClassLoader classLoader = YuWenWenApplicationContext.class.getClassLoader();
        // 得到类的包路径(此处为com.sbi.service格式需要改成com/sbi/service)
        URL resource = classLoader.getResource(path.value().replace(".", "/"));
        // 得到包下的文件
        File file = new File(resource.getFile());
        if (file.isDirectory()) {
            // 得到包下所有的文件信息
            File[] files = file.listFiles();
            for (File f : files) {
                String absolutePath = f.getAbsolutePath();
                String pathReplaceBefore = absolutePath
                    .substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
                String pathreplaceAfter = pathReplaceBefore.replace("\\", ".");
                // 此处最终需要com.sbi.service.YuWenWenService格式
                Class<?> aClass = classLoader.loadClass(pathreplaceAfter);

                // 如果这个类拥有@Component注解,那么我们就要反射
                if (aClass.isAnnotationPresent(Component.class)) {
                    //扫描@Comptent注解发现有实现BeanPostProcessor的类
                    if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
                        // 就将此类通过反射创建出来
                        BeanPostProcessor beanPostProcessor = (BeanPostProcessor) aClass.getDeclaredConstructor()
                            .newInstance();
                        // 将这个后置处理器加到list里
                        beanPostProcessorList.add(beanPostProcessor);
                    }
                    Component declaredAnnotation = aClass.getDeclaredAnnotation(Component.class);
                    // 拿到@Component的value值也就是bean的名字
                    String springbeanName = declaredAnnotation.value();
                    // 描述类创建
                    BeanDefinition beanDefinition = new BeanDefinition();
                    beanDefinition.setClazz(aClass);
                    // 判断这个类是否还持有@Scope的其他作用域(spring 一共有四种作用域,默认不指定的情况下就是单例)
                    if (aClass.isAnnotationPresent(Scope.class)) {
                        Scope declaredAnnotation1 = aClass.getDeclaredAnnotation(Scope.class);
                        beanDefinition.setScope(declaredAnnotation1.value());
                    } else {
                        // spring默认不指定的情况下就是单例作用域
                        beanDefinition.setScope("singleton");
                    }
                    // 将类信息放到beanDefinitionMap里
                    beanDefinitionMap.put(springbeanName, beanDefinition);
                }

            }
        }
    }

    public Object getBean(String beanName)
        throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        //去beanDefinitionMap寻找是否有自己的类描述
        if (beanDefinitionMap.containsKey(beanName)) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            //如果是单例bean,直接从单例池拿
            if (beanDefinition.getScope().equals("singleton")) {
                Object bean = singletonObjects.get(beanName);
                return bean;
                //如果是原型bean就给创建一个新的bean
            } else {
                Object bean = createBean(beanDefinition);
                return bean;
            }
            //没招到的情况下就说明此类并没有加@Competent
        } else {
            throw new NullPointerException("此类不存在");
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值