Spring IOC深度解析

该博客介绍了模拟实现Spring的IOC容器的实践过程。首先创建maven项目,接着配置web.xml和application.properties文件,创建5个与web相关的注解类、核心控制器类和ioc生成类,最后构建controller层和service层进行测试,项目启动注册成功。

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

1、创建maven项目spring20,模拟实现Spring的IOC容器

2、各个配置文件:
web.xml:用于servlet的启动配置
 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>mvc</servlet-name>
    <servlet-class>servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:application.properties</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>mvc</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

</web-app>

application.properties:配置spring相关信息,主要是扫描包的信息

scanPackage=demo

3、先创建与web相关的5个注解类:
 

package servlet.annotation;
 
import java.lang.annotation.*;
 
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    String value() default "";
}
package servlet.annotation;
 
import java.lang.annotation.*;
 
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {
    String value() default "";
}
package servlet.annotation;
 
import java.lang.annotation.*;
 
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {
    String value() default "";
}
package servlet.annotation;
 
import java.lang.annotation.*;
 
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    String value();
}
package servlet.annotation;
 
import java.lang.annotation.*;
 
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {
    String value() default "";
}


4、创建核心控制器类DispatcherServlet
 

package servlet;

import servlet.annotation.Autowired;
import servlet.annotation.Controller;
import servlet.annotation.Service;
import servlet.context.ApplicationContext;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
//Servlet只是作为mvc的启动入口
public class DispatcherServlet extends HttpServlet {
    private final String LOCATION="contextConfigLocation";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        ApplicationContext applicationContext=new ApplicationContext(config.getInitParameter(LOCATION));


    }


}

5、创建ioc生成类,主要包含这几个类,如下图所示:

package servlet.context.beans;

/**
 * 存储配置文件中的信息,相当于保存在内存中的配置
 */
public class BeanDefinition {

    private String beanClassName;

    private String factoryBeanName;

    private boolean lazyInit=false;

    public String getBeanClassName() {
        return beanClassName;
    }

    public void setBeanClassName(String beanClassName) {
        this.beanClassName = beanClassName;
    }

    public String getFactoryBeanName() {
        return factoryBeanName;
    }

    public void setFactoryBeanName(String factoryBeanName) {
        this.factoryBeanName = factoryBeanName;
    }

    public boolean isLazyInit() {
        return lazyInit;
    }

    public void setLazyInit(boolean lazyInit) {
        this.lazyInit = lazyInit;
    }

    //    public void setBeanClassName(String beanClassName){
//
//    }
//
//    public String getBeanCLassName(){
//        return null;
//    }
//
//    public void setFactoryBeanName(String factoryBeanName){
//
//    }
//
//    public String getFactoryBeanName(){
//        return null;
//    }
//
//    public void setLazyInit(boolean lazyInit){
//
//    }
//
//    public boolean isLazyInit(){
//        return false;
//    }

}
package servlet.context.beans;
//用于做事件监听
public class BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean,String beanName){
        return null;
    }
    public Object postProcessAfterInitializatioin(Object bean,String beanName){
        return null;
    }
}
package servlet.context.beans;

public class BeanWrapper {
    //还会用到观察者模式
    // 支持事件响应,会有一个监听

    private BeanPostProcessor beanPostProcessor;

    private Object wrapperInstance;
    //通过反射new出来的,要把它包装起来
    private Object originalInstance;

    public BeanWrapper(Object instance) {
        this.wrapperInstance = instance;
        this.originalInstance = instance;
    }

    public Object getWrappedInstance() {
        return this.wrapperInstance;
    }

    //返回代理以后的Class
    //可能会是$Proxy0
    public Class<?> getWrappedClass() {
        return this.wrapperInstance.getClass();
    }

    public BeanPostProcessor getBeanPostProcessor() {
        return beanPostProcessor;
    }

    public void setBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        this.beanPostProcessor = beanPostProcessor;
    }
}
package servlet.context.support;

import servlet.context.beans.BeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
//用于对配置文件查找,读取,解析
public class BeanDefinitiionReader {

    private Properties config=new Properties();

    private List<String> registyBeanClasses=new ArrayList<String>();
    //配置文件中用来获取自动扫描的包名的key
    private final String SCAN_PACKAGE="scanPackage";

    public BeanDefinitiionReader(String ... locations){
        //spring中通过reader去查找和定位
        InputStream is=this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:",""));
        try {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(null!=is) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        doScanner(config.getProperty(SCAN_PACKAGE));
    }

    public List<String> getRegistyBeanClasses(){
        return null;
    }

    public List<String> loadBeanDefinitions(){
        return this.registyBeanClasses;
    };
    //每注册一个className,就返回一个BeanDefinition,自己包装
    //BeanDefinition只是为了对配置信息进行包装
    public BeanDefinition registerBean(String className){
        if(this.registyBeanClasses.contains(className)){
            BeanDefinition beanDefinition=new BeanDefinition();
            beanDefinition.setBeanClassName(className);
            beanDefinition.setFactoryBeanName(toLowerFirstWord(className.substring(className.lastIndexOf(".")+1)));
            return beanDefinition;
        }
        return null;
    }

    //递归扫描所有相关联的class,保存在一个List中
    private void doScanner(String packageName){

        URL url=this.getClass().getClassLoader().getResource("/"+packageName.replaceAll("\\.","/"));
        File classDir=new File(url.getFile());
        for(File file:classDir.listFiles()){
            if(file.isDirectory()){
                doScanner(packageName+"."+file.getName());
            }else {
                registyBeanClasses.add(packageName+"."+file.getName().replace(".class",""));
            }
        }
    }

    private String toLowerFirstWord(String str){
        char[] charArr=str.toCharArray();
        charArr[0]+=32;
        return String.valueOf(charArr);
    }


    public Properties getConfig(){
        return this.config;
    }
}
package servlet.core;

public interface BeanFactory {

    Object getBean(String beanName);
}
package servlet.context;

import servlet.annotation.Autowired;
import servlet.annotation.Controller;
import servlet.annotation.Service;
import servlet.context.beans.BeanDefinition;
import servlet.context.beans.BeanPostProcessor;
import servlet.context.beans.BeanWrapper;
import servlet.context.support.BeanDefinitiionReader;
import servlet.core.BeanFactory;

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

public class ApplicationContext implements BeanFactory {

    private String[] configLocations;

    private BeanDefinitiionReader reader;
    //用来保存配置信息的map
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
    //用来保存注册是单例的容器
    private Map<String, Object> beanCacheMap = new HashMap<>();
    //用来存储所有的被代理过得对象
    private Map<String,BeanWrapper> beanWrapperMap = new ConcurrentHashMap<>();

    public ApplicationContext(String... configLocations) {
        this.configLocations = configLocations;
        refresh();
    }


    public void refresh() {


        //定位
        this.reader = new BeanDefinitiionReader(configLocations);

        //加载

        List<String> beanDefinitions = reader.loadBeanDefinitions();

        //注册
        doRegistry(beanDefinitions);

        //依赖注入,(lazy-init=false,执行依赖注入)
        //这里自动调用getBean方法
        doAutowired();
        System.out.println("IOC注册成功");
    }
    private void doAutowired(){
        for(Map.Entry<String,BeanDefinition> beanDefinitionEntry:beanDefinitionMap.entrySet()){
            //如果这个bean不是延迟加载,调用getBean方法进行实例化
            if(!beanDefinitionEntry.getValue().isLazyInit()){
                String beanName=beanDefinitionEntry.getKey();
                getBean(beanName);
            }
        }
    }
    //依赖注入
    public void populateBean(String bean,Object instance){
        Class clazz=instance.getClass();
        //对包含Controller.class和包含Service.class的类进行依赖注入
        if(clazz.isAnnotationPresent(Controller.class)||clazz.isAnnotationPresent(Service.class)){
            Field[] fields=clazz.getDeclaredFields();
            for (int i = 0; i <fields.length; i++) {
                Field field=fields[i];
                //如果字段内不包含autowire注释,跳过该字段继续循环
                if(!field.isAnnotationPresent(Autowired.class)){
                    continue;
                }
                Autowired autowired=field.getAnnotation(Autowired.class);
                //获取autowired注解的值
                String beanName=autowired.value().trim();
                //如果注解值为空,使用默认注解
                if("".equals(beanName)){
                    beanName=field.getType().getName();

                }
                Object object=beanWrapperMap.get(beanName).getWrappedInstance();
                field.setAccessible(true);
                try {
                    field.set(instance,object);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // 真正的将beanDefiniton注册到beanDefinitionMap
    private void doRegistry(List<String> beanDefinitions) {
        //beanName有三种情况
        //1、默认首字母小写
        //2、自定义名字
        //3、接口注入
        try {
            for (String className : beanDefinitions) {
                Class<?> beanClass = Class.forName(className);
                if (beanClass.isInterface()) {
                    continue;
                }
                BeanDefinition beanDefinition = reader.registerBean(className);
                if(beanDefinition!=null){
                    this.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(),beanDefinition);
                }

                Class<?>[] interfaces=beanClass.getInterfaces();

                for (Class clazz:interfaces
                     ) {
                this.beanDefinitionMap.put(clazz.getName(),beanDefinition);
                }
                //到这里为止,容器初始化完毕
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //依赖注入从这里开始,通过读取BeanDefinition中的信息,
    //然后,通过反射机制创建一个实例,并返回
    //Spring的做法是,不会把最原始的对象放出去,会用一个BeanWrapper来进行一次包装
    //装饰器模式,
    //1、保留原来的OOP关系
    //2、我需要对他进行扩展和增强
    @Override
    public Object getBean(String beanName) {
        BeanDefinition beanDefinition=this.beanDefinitionMap.get(beanName);
        String className=beanDefinition.getBeanClassName();
        try{
            //生成通知事件
            BeanPostProcessor beanPostProcessor=new BeanPostProcessor();

            Object instance=instantionBean(beanDefinition);
            if(null==instance){
                return null;
            }
            //实例初始化以前调用一次
            beanPostProcessor.postProcessBeforeInitialization(instance,beanName);
            BeanWrapper beanWrapper=new BeanWrapper(instance);
            beanWrapper.setBeanPostProcessor(beanPostProcessor);
            this.beanWrapperMap.put(beanName,beanWrapper);
            //实例初始化以后调用一次
            beanPostProcessor.postProcessAfterInitializatioin(instance,beanName);
            populateBean(beanName,instance);
            //通过这样一调用,相当于给自己留下了可操作空间
            return this.beanWrapperMap.get(beanName).getWrappedInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    //传一个beanDefinition,返回一个instance
    private Object instantionBean(BeanDefinition beanDefinition){
        Object instance=null;
        String className=beanDefinition.getBeanClassName();
        try {
            //根据class才能确定一个类是否有实例
            if(this.beanCacheMap.containsKey(className)){
                instance=this.beanCacheMap.get(className);
            }else{
                Class clazz=Class.forName(className);
                instance=clazz.newInstance();
                beanCacheMap.put(className,instance);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return instance;
    }
}

6、测试,构建controller层和service层:

 

package demo.controller;

import demo.service.IService;
import servlet.annotation.Autowired;
import servlet.annotation.Controller;
import servlet.annotation.RequestMapping;
import servlet.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
public class DemoController {
    @Autowired
    IService iService;
    @RequestMapping("/getInfo")
    public void getInfo(@RequestParam("param") String param){
        iService.add();
    }
    @RequestMapping("/doTest")
    public void test1(HttpServletRequest request, HttpServletResponse response,
                      @RequestParam("param") String param){
        System.out.println(param);
        try {
            response.getWriter().write( "doTest method success! param:"+param);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @RequestMapping("/doTest2")
    public void test2(HttpServletRequest request, HttpServletResponse response){
        try {
            response.getWriter().println("doTest2 method success!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package demo.service;

import servlet.annotation.Service;


public interface IService {

    public void add();
}
package demo.service.impl;

import demo.service.IService;
import servlet.annotation.Service;

@Service
public class IServiceImpl implements IService {
    @Override
    public void add() {
        System.out.println("新增一条数据");
    }
}

 

启动项目结果如下图,注册成功!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值