实现一个简易版的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 bean的Class对象 * @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."); } } /* * 处理字段注入 * 先AutowiredByName后AutowiredByType */ // 获取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); } } // 调用InitializingBean的afterPropertiesSet()方法 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的参数固定为target、method和args 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)方法执行完成后,代理对象返回执行结果或者抛异常
评论