0


Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架

简单手写SpringIOC框架

环境搭建

基于XML方式

项目结构

在这里插入图片描述

项目代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com</groupId><artifactId>spring</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.1.RELEASE</version></dependency></dependencies></project>

UserBean.java

packagecom.spring.bean;/**
 * @author honey
 * @date 2023-08-08 14:58:16
 */publicclassUserBean{}

spring.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="userBean"class="com.spring.bean.UserBean"/></beans>

SpringTest01.java

packagecom.spring.test;importcom.spring.bean.UserBean;importorg.springframework.context.support.ClassPathXmlApplicationContext;/**
 * @author honey
 * @date 2023-08-08 14:59:56
 */publicclassSpringTest01{publicstaticvoidmain(String[] args){// 读取spring.xmlClassPathXmlApplicationContext applicationContext =newClassPathXmlApplicationContext("spring.xml");// 从IOC容器中读取对象UserBean userBean = applicationContext.getBean("userBean",UserBean.class);System.out.println(userBean);}}

运行结果

在这里插入图片描述

基于注解方式

项目结构

在这里插入图片描述

项目代码

ScanBean.java

packagecom.spring.bean.scan;importorg.springframework.stereotype.Component;/**
 * @author honey
 * @date 2023-08-08 16:37:26
 */@ComponentpublicclassScanBean{}

SpringConfig.java

packagecom.spring.config;importcom.spring.bean.UserBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;/**
 * @author honey
 * @date 2023-08-08 16:30:21
 */@Configuration@ComponentScan(value ={"com.spring.bean.scan"})publicclassSpringConfig{@Bean(name ="user")publicUserBeanuserBean(){returnnewUserBean();}}

SpringTest02.java

packagecom.spring.test;importcom.spring.bean.UserBean;importcom.spring.bean.scan.ScanBean;importcom.spring.config.SpringConfig;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;/**
 * @author honey
 * @date 2023-08-08 16:31:25
 */publicclassSpringTest02{publicstaticvoidmain(String[] args){// 加载SpringConfigAnnotationConfigApplicationContext applicationContext =newAnnotationConfigApplicationContext(SpringConfig.class);// 从IOC容器中读取对象UserBean userBean = applicationContext.getBean("user",UserBean.class);System.out.println(userBean);ScanBean scanBean = applicationContext.getBean("scanBean",ScanBean.class);System.out.println(scanBean);}}

运行结果

在这里插入图片描述

简单手写SpringIOC框架

核心原理

底层使用map集合管理对象,key=beanId,value=实例对象

privatefinalMap<String,Object> beanMap =newConcurrentHashMap<>();

基于XML方式

原理

基于反射+工厂模式+DOM技术

  1. 使用DOM技术解析spring.xml文件;
  2. 获取bean的id和class属性;
  3. 根据类的完整路径使用反射技术初始化对象;
  4. 使用工厂模式管理初始化对象;

项目结构

在这里插入图片描述

项目代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com</groupId><artifactId>ext-spring-ioc</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency></dependencies></project>

UserBean.java

packagecom.spring.bean;/**
 * @author honey
 * @date 2023-08-08 16:56:32
 */publicclassUserBean{}

spring.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="userBean"class="com.spring.bean.UserBean"/></beans>

SpringIocXml.java

packagecom.spring.ext;importorg.dom4j.Document;importorg.dom4j.DocumentException;importorg.dom4j.Element;importorg.dom4j.io.SAXReader;importorg.springframework.core.io.ClassPathResource;importjava.io.File;importjava.io.IOException;importjava.util.List;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;/**
 * @author honey
 * @date 2023-08-08 16:57:17
 */publicclassSpringIocXml{privatefinalMap<String,Object> beanMap =newConcurrentHashMap<>();publicSpringIocXml()throwsIOException,DocumentException{init();}public<T>TgetBean(String name){return(T) beanMap.get(name);}/**
     * 初始化IOC容器
     */privatevoidinit()throwsIOException,DocumentException{// 解析spring.xml配置ClassPathResource classPathResource =newClassPathResource("spring.xml");File xmlFile = classPathResource.getFile();SAXReader saxReader =newSAXReader();Document doc = saxReader.read(xmlFile);// 获取根节点Element rootElement = doc.getRootElement();// 获取bean节点信息List<Element> beans = rootElement.elements("bean");for(Element bean : beans){try{String beanId = bean.attribute("id").getValue();String classPath = bean.attribute("class").getValue();// 使用反射机制初始化对象,并将对象存入Map集合Class<?> clazz =Class.forName(classPath);Object object = clazz.newInstance();
                beanMap.put(beanId, object);}catch(Exception e){
                e.printStackTrace();}}}}

SpringTest01.java

packagecom.spring.test;importcom.spring.bean.UserBean;importcom.spring.ext.SpringIocXml;importorg.dom4j.DocumentException;importjava.io.IOException;/**
 * @author honey
 * @date 2023-08-08 17:04:35
 */publicclassSpringTest01{publicstaticvoidmain(String[] args)throwsDocumentException,IOException{SpringIocXml springIocXml =newSpringIocXml();UserBean userBean = springIocXml.getBean("userBean");System.out.println(userBean);}}

运行结果

在这里插入图片描述

基于注解方式

原理

基于反射+工厂模式实现

  1. 判断配置类上是否有@Configuration注解;
  2. 获取配置类中的所有方法,判断方法上是否有@Bean注解,如果有则获取方法的返回值作为实例对象;
  3. 判断配置类上是否有@ComponentScan注解,如果有则扫描指定包下的所有类,并判断类上是否有@Component注解,如果有则通过反射技术初始化对象;
  4. 使用工厂模式管理初始化对象/实例对象;

项目结构

在这里插入图片描述

项目代码

pom.xml

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.7</version></dependency>

ScanBean.java

packagecom.spring.bean.scan;importorg.springframework.stereotype.Component;/**
 * @author honey
 * @date 2023-08-09 14:28:33
 */@ComponentpublicclassScanBean{}

SpringConfig.java

packagecom.spring.config;importcom.spring.bean.UserBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;/**
 * @author honey
 * @date 2023-08-09 14:26:40
 */@Configuration@ComponentScan(value ={"com.spring.bean.scan"})publicclassSpringConfig{@BeanpublicUserBeanuserBean(){returnnewUserBean();}}

SpringIocAnnotation.java

packagecom.spring.ext;importcn.hutool.core.lang.ClassScanner;importcn.hutool.core.util.StrUtil;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;importorg.springframework.stereotype.Component;importjava.lang.annotation.Annotation;importjava.lang.reflect.Method;importjava.util.Map;importjava.util.Set;importjava.util.concurrent.ConcurrentHashMap;/**
 * @author honey
 * @date 2023-08-09 14:12:21
 */publicclassSpringIocAnnotation{privatefinalObject config;privatefinalMap<String,Object> beanMap =newConcurrentHashMap<>();publicSpringIocAnnotation(Object config){this.config = config;init();}/**
     * 初始化IOC容器
     */publicvoidinit(){// 判断配置类上是否有@Configuration注解Configuration configuration =this.config.getClass().getDeclaredAnnotation(Configuration.class);if(configuration ==null){return;}// 处理@Bean注解Class<?> clazz = config.getClass();Method[] declaredMethods = clazz.getDeclaredMethods();for(Method method : declaredMethods){// 判断方法上是否有@Bean注解Bean bean = method.getDeclaredAnnotation(Bean.class);if(bean !=null){try{// 获取beanIdString[] value = bean.value();String beanId = value.length >0? value[0]: method.getName();// 获取方法的返回值Object object = method.invoke(config);
                    beanMap.put(beanId, object);}catch(Exception e){
                    e.printStackTrace();}}}// 处理@Component注解ComponentScan componentScan = clazz.getDeclaredAnnotation(ComponentScan.class);if(componentScan !=null){for(String packageName : componentScan.value()){try{// 扫描指定包下的所有类Set<Class<?>> classes =ClassScanner.scanPackage(packageName);for(Class<?> c : classes){// 判断类上是否有@Component注解Annotation component = c.getDeclaredAnnotation(Component.class);if(component !=null){try{// 获取beanIdString beanId =StrUtil.lowerFirst(c.getSimpleName());// 通过反射技术初始化对象Object beanObject = c.newInstance();
                                beanMap.put(beanId, beanObject);}catch(Exception e){
                                e.printStackTrace();}}}}catch(Exception e){
                    e.printStackTrace();}}}}public<T>TgetBean(String name){return(T) beanMap.get(name);}}

SpringTest02.java

packagecom.spring.test;importcom.spring.bean.UserBean;importcom.spring.bean.scan.ScanBean;importcom.spring.config.SpringConfig;importcom.spring.ext.SpringIocAnnotation;/**
 * @author honey
 * @date 2023-08-09 14:24:36
 */publicclassSpringTest02{publicstaticvoidmain(String[] args){SpringIocAnnotation springIocAnnotation =newSpringIocAnnotation(newSpringConfig());UserBean userBean = springIocAnnotation.getBean("userBean");System.out.println(userBean);ScanBean scanBean = springIocAnnotation.getBean("scanBean");System.out.println(scanBean);}}

运行结果

在这里插入图片描述

标签: mr java 开发语言

本文转载自: https://blog.csdn.net/sinat_41888963/article/details/132168882
版权归原作者 Mr. Cappuccino 所有, 如有侵权,请联系我们删除。

“Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架”的评论:

还没有评论