mySpring 正在参加 2021 年度 OSC 中国开源项目评选,请投票支持!
mySpring 在 2021 年度 OSC 中国开源项目评选 中已获得 {{ projectVoteCount }} 票,请投票支持!
2021 年度 OSC 中国开源项目评选 正在火热进行中,快来投票支持你喜欢的开源项目!
2021 年度 OSC 中国开源项目评选 >>> 中场回顾
mySpring 获得 2021 年度 OSC 中国开源项目评选「最佳人气项目」 !
授权协议 Apache-2.0
开发语言 Java
操作系统 跨平台
软件类型 开源软件
所属分类 Web应用开发Web框架
开源组织
地区 国产
投 递 者 WenmengWang
适用人群 未知
收录时间 2024-08-16

软件简介

实现一个简易版的Spring框架,主要包括IOC(Inversion of Control,控制反转)和AOP(Aspect-Oriented Programming,面向切面编程)两个核心功能.

通过控制反转,将依赖对象的创建和管理交给IOC容器,类只需要声明依赖关系,具体的依赖由容器注入。这样,类与类之间的依赖关系通过接口而非实现进行耦合,降低了代码的耦合度,使得系统更易于维护和扩展,为了简化代码,本文是由注解的方式进行的,以下是IOC的设计流程图。

(1)添加注解源信息,主要是定义了三个注解@Autowired、@Component 、@ComponentScan,其作用就是为了避免使用XML的形式进行读取类信息,直接通过注解进行扫描读取类的信息,其主要的核心代码如下所示。

package com.ioc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
    boolean required() default true;
}
package com.ioc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {

    String value() default "";
}
package com.ioc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {

    String value();
}

(2)定义BeanFactory接口,用于管理和获取Bean。BeanFactory负责提供容器内对象的实例化、配置和生命周期管理。它是Spring IOC容器的最基本的接口,用于定义Bean的获取方式,其核心代码如下所示:

package com.ioc;

public interface BeanFactory<T> {

    Object getBean(String beanName);

    T getBean(Class<T> type);

    T getBean(String beanName, Class<T> type);
}

(3) BeanDefinition类是非常重要的一个类,它用于描述一个 Bean 的配置信息,包括 Bean 的类名、作用域、依赖关系、初始化方法等,其核心代码如下所示。

package com.ioc;

public class BeanDefinition {

    /**
     * bean的类型
     */
    private Class type;

    /**
     * bean的作用域
     */
    private String scope;

    /**
     * 是否懒加载
     */
    private boolean lazy;

    public Class getType() {
        return type;
    }

    public void setType(Class type) {
        this.type = type;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public boolean isLazy() {
        return lazy;
    }

    public void setLazy(boolean lazy) {
        this.lazy = lazy;
    }

}

(4)AnnotationConfigApplicationContext类是容器的核心类也是最核心的一个类,主要流程是读取注解的类信息,扫描特定注解的类如@Component,并将这些类解析成BeanDefinition对象,然后根据BeanDefinition中的信息,创建Bean实例,对于单例的Bean,将实例化的Bean保存到SingletonObjects中,以便于后续重复使用,对于非单例对象,每次请求都重新创建一个新实例,并且根据作用域管理生命周期,然后进行初始化前后的逻辑,初始化前后的逻辑允许用户完成功能增强的行为,代理的创建、以及属性的修改都在在这里完成的,然后进行懒加载的处理,在Spring容器启动时不立即创建实例,而是需要用到对象的时候才进行加载,其核心代码如下所示:

package com.ioc;

import com.ioc.annotation.*;
import com.ioc.exception.NoSuchBeanException;
import com.ioc.exception.TooMuchBeanException;

import java.io.File;
import java.lang.reflect.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;


public class AnnotationConfigApplicationContext<T> implements ApplicationContext<T> {

    private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    /**
     * 单例对象池
     */
    private final Map<String, Object> singletonObjects = new HashMap<>();

    /**
     * 保存所有BeanPostProcessor接口实现类的集合
     */
    List<BeanPostProcessor> list = new ArrayList<>();

    /**
     * 创建Spring容器时指定的配置类
     */
    public final Class<T> configClass;

    public AnnotationConfigApplicationContext(Class<T> configClass) throws ClassNotFoundException {
        this.configClass = configClass;

        // 扫描组件
        scan(configClass);

        // 把组件中非懒加载的单例bean保存到单例池
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            BeanDefinition beanDefinition = entry.getValue();

            if(isSingleton(beanDefinition.getScope()) && !beanDefinition.isLazy()) {
                Object bean = createBean(beanDefinition);
                String beanName = entry.getKey();

                singletonObjects.put(beanName, bean);
            }
        }
    }

    /**
     * 扫描组件
     * @param clazz 配置类的类对象
     * @throws ClassNotFoundException 类找不到
     */
    private void scan(Class<T> clazz) throws ClassNotFoundException {
        // 如果类上使用了@ComponentScan注解
        if (clazz.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = clazz.getAnnotation(ComponentScan.class);
            String value = componentScan.value();

            if (!"".equals(value)) {
                String path = value;
                path = path.replace(".", "/");

                URL resource = clazz.getClassLoader().getResource(path);
                File file = new File(resource.getFile());

                loopFor(file);
            }
        }
    }

    /**
     * 递归遍历指定文件/文件夹
     * @param file 文件/文件夹
     * @throws ClassNotFoundException 类找不到
     */
    private void loopFor(File file) throws ClassNotFoundException {
        if (file.isDirectory()) {
            for (File listFile : file.listFiles()) {
                if (listFile.isDirectory()) {
                    loopFor(listFile);

                    continue;
                }

                toBeanDefinitionMap(listFile);
            }
        } else if (file.isFile()) {
            toBeanDefinitionMap(file);
        }
    }

    /**
     * 解析bean,并保存到Map<String, BeanDefinition>
     * @param file 解析的class文件
     * @throws ClassNotFoundException 类找不到
     */
    private void toBeanDefinitionMap(File file) throws ClassNotFoundException {
        // 获取类的绝对路径
        String absolutePath = file.getAbsolutePath();
        // 处理得到类的全限定名
        absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
        absolutePath = absolutePath.replace("\\", ".");

        // 通过类加载器加载
        Class<?> loadClass = configClass.getClassLoader().loadClass(absolutePath);

        if (loadClass.isAnnotationPresent(Component.class)) {
            Component component = loadClass.getAnnotation(Component.class);
            String beanName = component.value();

            if ("".equals(beanName)) {
                beanName = getBeanName(loadClass);
            }

            boolean lazy = false;
            String scope = "singleton";

            // 类上使用了@Scope注解
            if (loadClass.isAnnotationPresent(Scope.class)) {
                // 获取@Scope注解
                Scope annotation = loadClass.getAnnotation(Scope.class);

                // 单例
                if (isSingleton(annotation.value())) {
                    lazy = loadClass.isAnnotationPresent(Lazy.class);
                } else {
                    // 非单例
                    scope = annotation.value();
                }
            } else {
                // 类上没有使用@Scope注解,默认是单例的
                lazy = loadClass.isAnnotationPresent(Lazy.class);
            }

            // 保存bean的定义
            BeanDefinition beanDefinition = new BeanDefinition();

            beanDefinition.setType(loadClass);
            beanDefinition.setLazy(lazy);
            beanDefinition.setScope(scope);

            // BeanPostProcessor接口的实现类保存到list
            if (BeanPostProcessor.class.isAssignableFrom(loadClass)) {
                list.add((BeanPostProcessor) createBean(beanDefinition));
            } else {
                beanDefinitionMap.put(beanName, beanDefinition);
            }
            beanDefinitionMap.put(beanName, beanDefinition);
        } else if (loadClass.isAnnotationPresent(Configuration.class)) {
            Method[] methods = loadClass.getDeclaredMethods();

            for (Method method : methods) {
                if (method.isAnnotationPresent(Bean.class)) {
                    Bean annotation = method.getAnnotation(Bean.class);
                    String beanName = annotation.value();

                    // 是否懒加载
                    boolean lazy = method.isAnnotationPresent(Lazy.class);
                    // 作用域
                    String scope = "singleton";

                    if ("".equals(beanName)) {
                        beanName = method.getName();
                    }

                    // 保存bean的定义
                    BeanDefinition beanDefinition = new BeanDefinition();

                    // 方法的返回值类型就是bean的类型
                    beanDefinition.setType(method.getReturnType()); // 方法的返回值类型就是bean的类型
                    beanDefinition.setLazy(lazy);
                    beanDefinition.setScope(scope);

                    // BeanPostProcessor接口的实现类保存到list
                    if (BeanPostProcessor.class.isAssignableFrom(loadClass)) {
                        list.add((BeanPostProcessor) createBean(beanDefinition));
                    } else {
                        beanDefinitionMap.put(beanName, beanDefinition);
                    }
                }
            }
        }
    }

    /**
     * 根据类对象获取beanName
     * @param clazz beanClass对象
     * @return String bean名称
     */
    private String getBeanName(Class<?> clazz) {
        String beanName = clazz.getSimpleName();

        // 判断是否以双大写字母开头
        String className = beanName.replaceAll("([A-Z])([A-Z])", "$1_$2");

        // 正常的大驼峰命名:bean名称为类名首字母大写
        if (className.indexOf("_") != 1) {
            beanName = beanName.substring(0, 1).toLowerCase().concat(beanName.substring(1));
        } else { // 否则,bean名称为类名
            beanName = beanName;
        }

        return beanName;
    }

    /**
     * 判断作用域是否单例
     * @param scope bean的作用域
     * @return boolean 如果是单例,返回true,否则返回false
     */
    private boolean isSingleton(String scope) {
        return "singleton".equals(scope);
    }

    /**
     * 创建bean对象
     * @param beanDefinition bean的定义
     * @return Object 创建好的bean对象
     */
    private Object createBean(BeanDefinition beanDefinition) {
        Object bean = null;
        Class beanType = beanDefinition.getType();

        // 获取所有构造方法
        Constructor[] constructors = beanType.getConstructors();

        try {
            /*
             * 推断构造方法
             * 1、没有提供构造方法:调用默认的无参构造
             * 2、提供了构造方法:
             *   - 构造方法个数为1
             *     - 构造方法参数个数为0:无参构造
             *     - 构造方法参数个数不为0:传入多个为空的参数
             *   - 构造方法个数 > 1
             *     - 提供了无参构造方法:调用无参构造方法实例化
             *     - 没有提供无参构造方法:推断失败,抛出异常
             */
            if (isEmpty(constructors)) { // 注意:这个分支永远不会执行,可以删除,但是为了方便理解代码,在此保留
                // 无参构造方法
                Constructor constructor = beanType.getConstructor();

                bean = constructor.newInstance();
            } else if (constructors.length == 1) {
                Constructor constructor = constructors[0];
                // 得到构造方法参数个数
                int parameterCount = constructor.getParameterCount();

                if (parameterCount == 0) {
                    // 无参构造方法
                    bean = constructor.newInstance();
                } else {
                    // 多个参数的构造方法
                    Object[] array = new Object[parameterCount];

                    bean = constructor.newInstance(array);
                }
            } else {
                boolean success = false;

                for (Constructor constructor : constructors) {
                    if (constructor.getParameterCount() == 0) {
                        bean = constructor.newInstance();
                        success = true;
                        break;
                    }
                }

                if (!success) {
                    throw new IllegalStateException("No default constructor found.");
                }
            }

            /*
             * 处理字段注入
             * AutowiredByNameAutowiredByType
             */
            // 获取bean的所有自定义属性
            Field[] fields = beanType.getDeclaredFields();

            for (Field field : fields) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    // 获取bean
                    // 通过bean名称获取bean
                    Object autowiredBean = getBean(field.getName());

                    // 没有找到对应名称的bean,尝试通过bean类型查找,bean的类型就是该字段的类型
                    if (autowiredBean == null) {
                        // 获取字段类型
                        Class<?> type = field.getType();

                        autowiredBean = getBean((Class<T>) type);
                    }

                    // 并设置到@Autowired注入的属性中
                    field.setAccessible(true);
                    field.set(bean, autowiredBean);
                }
            }

            /*
             * 处理构造方法注入
             */
           for (Constructor constructor : constructors) {
                if (constructor.getParameterCount() > 0) {
                   for (Parameter parameter : constructor.getParameters()) {
                        // 如果参数类型是一个bean,则注入
                       // 通过bean名称获取bean
                        Object autowiredBean = getBean(parameter.getName());

                       // 没有找到对应名称的bean,尝试通过bean类型查找,bean的类型就是该字段的类型
                        if (autowiredBean == null) {
                            // 获取字段类型
                            Class type = parameter.getType();
                              autowiredBean = getBean((Class<T>) type);
                        }
                    }
                }
            }
            Method[] methods = beanType.getDeclaredMethods();

            for (Method method : methods) {
                if (method.getParameterCount() > 0) {
                    Class<?>[] parameterTypes = method.getParameterTypes();

                    for (Class<?> parameterType : parameterTypes) {
                        // 如果参数类型是一个bean,则注入
                        // 通过bean名称获取bean
                        Object autowiredBean = getBean(parameterType.getName());

                        // 没有找到对应名称的bean,尝试通过bean类型查找,bean的类型就是该字段的类型
                        if (autowiredBean == null) {
                            autowiredBean = getBean((Class<T>) parameterType);
                        }
                    }
                }
            }

            /*
             * 初始化前
             */
            String beanName = getBeanName(beanDefinition.getType());

            if (!list.isEmpty()) {
                for (BeanPostProcessor beanPostProcessor : list) {
                    bean = beanPostProcessor.postProcessBeforeInitialization(bean, beanName);
                }
            }

            // 调用InitializingBeanafterPropertiesSet()方法
            if (bean instanceof InitializingBean) {
                Method afterPropertiesSet = beanType.getDeclaredMethod("afterPropertiesSet");
                afterPropertiesSet.invoke(bean);
                ((InitializingBean) bean).afterPropertiesSet();
            }
            /*
             * 初始化后
             */
            if (list.size() > 0) {
                for (BeanPostProcessor beanPostProcessor : list) {
                    bean = beanPostProcessor.postProcessAfterInitialization(bean, beanName);
                }
            }
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }

        return bean;
    }

    private boolean isEmpty(Object[] array) {
        return array.length == 0;
    }

    @Override
    public Object getBean(String beanName) {
        if (!beanDefinitionMap.containsKey(beanName)) {
            return null;
        }

        return getBean(beanName, beanDefinitionMap.get(beanName));
    }

    @Override
    public T getBean(Class<T> type) {
        if (type == null) {
            throw new IllegalStateException("bean类型不能为空!");
        }

        // 保存指定类型的bean的个数
        AtomicInteger count = new AtomicInteger();
        // 保存同一类型的bean
        Map<String, BeanDefinition> objectMap = new HashMap<>();

        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            BeanDefinition beanDefinition = entry.getValue();
            Class beanType = beanDefinition.getType();
            String beanName = entry.getKey();

            if (beanType.equals(type)) {
                count.addAndGet(1);
                objectMap.put(beanName, beanDefinition);
            }
        }

        if (count.get() == 0) {
            throw new NoSuchBeanException();
        } else if (count.get() > 1) {
            throw new TooMuchBeanException();
        } else {
            return (T) getBean((String) objectMap.keySet().toArray()[0], (BeanDefinition) objectMap.values().toArray()[0]);
        }
    }

    @Override
    public T getBean(String beanName, Class<T> type) {
        if (type == null) {
            throw new IllegalStateException("bean类型不能为空!");
        }
        if (beanDefinitionMap.containsKey(beanName)) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);

            if (type.equals(beanDefinition.getType())) {
                return (T) getBean(beanName, beanDefinition);
            }
        }

        throw new NoSuchBeanException();
    }

    /**
     * 统一获取bean的方法
     * @param beanName bean名称
     * @param beanDefinition BeanDefinition
     * @return Object 符合条件的bean对象
     */
    private Object getBean(String beanName, BeanDefinition beanDefinition) {
        String scope = beanDefinition.getScope();

        // bean的作用域是单例
        if (isSingleton(scope)) {
            Object object = singletonObjects.get(beanName);

            // 懒加载的单例bean
            if (object == null) {
                Object bean = createBean(beanDefinition);

                singletonObjects.put(beanName, bean);
            }

            return singletonObjects.get(beanName);
        }

        return createBean(beanDefinition);
    }

}

AOP是一种编程范式,它允许将横切关注点(如日志、事务管理、权限控制等)从业务逻辑中分离出来,以模块化的方式进行管理。AOP的实现主要依赖于动态代理机制,本文主要是使用了jdk动态代理以及cglib动态代理。

(1)定义切面、切点、以及通知主要是为了定义了在应用程序的哪些位置应用特定的行为,其核心代码如下所示

package com.aop.test2.bean;

import org.aspectj.weaver.tools.PointcutExpression;

public interface Pointcut {

    public String getExpression();

    /**
     * 转换为AspectJ的切入点表达式
     * @return
     */
    public PointcutExpression buildPointcutExpression();

}
package com.aop.test2.bean;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Advice {
    private Method adviceMethod;
    private Aspect aspect;

    public void invokeAspectMethod(final Object target, final Method method, final Object[] args) {
        // 假设advice的参数固定为targetmethodargs
        try {
            adviceMethod.invoke(aspect, target, method, args);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public Advice(Method adviceMethod, Aspect aspect) {
        this.adviceMethod = adviceMethod;
        this.aspect = aspect;
    }

}
package com.aop.test2.bean;

import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;

public class AspectJPointcut implements Pointcut {

    public String expression;

    public AspectJPointcut(String expression) {
        this.expression = expression;
    }

    @Override
    public String getExpression() {
        return this.expression;
    }

    @Override
    public PointcutExpression buildPointcutExpression() {
        PointcutParser parser = PointcutParser
        .getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution();
        return parser.parsePointcutExpression(this.expression);
    }

}

(2)生成代理对象当容器启动时,AOP会根据配置生成目标类的代理对象,并将切面逻辑织入到代理对象中,其核心代码如下所示

package com.aop.proxy;

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

public class JDKProxy {
    /**
     * 创建target的代理对象
     * @param target
     * @return
     */
    private static Object createProxy(final Object target) {
        return Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), target.getClass().getInterfaces(),new MyHandler(target));
    }

    public static void main(final String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        final BizAImpl bizAImpl = new BizAImpl();
        final IBizA newBizA = (IBizA) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),
                bizAImpl.getClass().getInterfaces(),
                new MyHandler(bizAImpl));
        newBizA.doSomething();
    }

}

/**
 * 在代理的接口调用时的处理器类
 */
class MyHandler implements InvocationHandler {
    private final Object target;
    public MyHandler(final Object target) {
        this.target = target;
    }

    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
        System.out.println("-----before----");
        final Object o = method.invoke(this.target, args);
        System.out.println("-----after----");
        return o;
    }
}
package com.aop.cglib;

import java.lang.reflect.Method;

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

public class CglibProxy {
    public static void main(String[] args) {
        MyHandler myHandler = new MyHandler();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(BizA.class);
        enhancer.setCallback(myHandler);;
    }
}

class MyHandler implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("----before----");
        Object o = proxy.invokeSuper(obj, args);
        System.out.println("----after----");
        return o;
    }
}

(3)只想BeforAdvice以及AfterAdvice主要是为了方法增强,完成统一的额外功能。

package com.aop.test2.bean;

import java.lang.reflect.Method;

import com.aop.test2.interceptor.MethodInterceptorChain;
import com.aop.test2.interceptor.MyMethodInterceptor;

public class BeforeAdvice extends Advice implements MyMethodInterceptor {
    public BeforeAdvice(Method adviceMethod, Aspect aspect) {
        super(adviceMethod, aspect);
        // TODO Auto-generated constructor stub
    }

    public void before(final Object target, final Method method, final Object[] args) {
        this.invokeAspectMethod(target, method, args);
        ;
    }

    @Override
    public Object intercept(Method method, Object[] arguments, Object target, MethodInterceptorChain chain) {
        this.before(target, method, arguments);
        return chain.intercept(method, arguments, target);
    }
}
package com.aop.test2.bean;

import java.lang.reflect.Method;

import com.aop.test2.interceptor.MethodInterceptorChain;
import com.aop.test2.interceptor.MyMethodInterceptor;

public class AfterAdvice extends Advice implements MyMethodInterceptor {

    public AfterAdvice(Method adviceMethod, Aspect aspect) {
        super(adviceMethod, aspect);
        // TODO Auto-generated constructor stub
    }

    public void after(final Object target, final Method method, final Object[] args) {
        this.invokeAspectMethod(target, method, args);
    }

    @Override
    public Object intercept(Method method, Object[] arguments, Object target, MethodInterceptorChain chain) {
        Object obj = chain.intercept(method, arguments, target);
        this.after(target, method, arguments);
        return obj;
    }
}

(4)方法执行完成后,代理对象返回执行结果或者抛异常

展开阅读全文

代码

的 Gitee 指数为
超过 的项目

评论

点击引领话题📣 发布并加入讨论🔥
暂无内容
发表了博客
{{o.pubDate | formatDate}}

{{formatAllHtml(o.title)}}

{{parseInt(o.replyCount) | bigNumberTransform}}
{{parseInt(o.viewCount) | bigNumberTransform}}
没有更多内容
暂无内容
发表了问答
{{o.pubDate | formatDate}}

{{formatAllHtml(o.title)}}

{{parseInt(o.replyCount) | bigNumberTransform}}
{{parseInt(o.viewCount) | bigNumberTransform}}
没有更多内容
暂无内容
暂无内容
0 评论
1 收藏
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部