SpringIoc模拟实现Demo

原理:SpringIoC控制反转底层实现利用了java自身提供的反射技术来创建对象

Class.forName(classPath).newInstance();

 通过这种方式,spring控制了对象的生命周期,可以随时自行增强对象,如DI依赖注入,如AOP,环绕通知在类创建前后增强功能,如Transaction事务加强等。

开发步骤

  1. 创建容器管理bean,并初始化容器-> [user,dept,hello]
  2. 创建spring容器,并初始化容器-> {hello=new Hello(),user=new Uer() }
  3. 提供getBean(),根据bean的名字,从spring容器中获取对应的对象

Bean.java

抽象Bean的定义,取代java中的Object,Spring框架中万物皆Bean。

package com;
/**
 * Spring中万物皆是Bean,用于存放对象
 * 管理Bean也是管理对象
 * */
public class Bean {
    //Bean的名字Id
    private String name;
    //Bean(java中的对象)对应的路径“包名.类名”
    private String path;

    /**
     * 生成get,set方法给对象赋值
     * */
    public String getName() {
        return name;
    }

    public String getPath() {
        return path;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPath(String path) {
        this.path = path;
    }
}

SpringContext.java

逻辑复杂,IoC实现的核心,最关键点还是怎么创建对象实例:

package com;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 模拟spring框架
 * 创建Bean
 * 存放Bean
 * 设置取出Bean的方法,有Bean就直接取出没有需要创建一个
 * */
public class SpringContext {
    //创建一个容器存放Bean
    private List<Bean> beanFactory = new ArrayList<>();
    //构造方法创建框架是自动执行
    public SpringContext() throws Exception {
        //创建一个Bean
        Bean bean = new Bean();

        bean.setName("Hello");
        bean.setPath("com.Hello");
        //将Bean加入容器
        beanFactory.add(bean);
        init();
    }

    /**
     * 创建容器Key是类名Value是路径
     * 通过Class.forName(path).newInstance()获取对象
     * */
    private final Map<String, Object> factoryBeanObject =
            new ConcurrentHashMap<>();
    public void init() throws Exception {
        for(Bean b : beanFactory){
            String key = b.getName();
            //反射创建对象,作为value存入map
            String path = b.getPath();
            Object value = Class.forName(path).newInstance();
            factoryBeanObject.put(key, value);
        }
    }

    //3,getBean()有就直接取出来,没有就创建并放入容器
    public Object getBean (String name){
        return factoryBeanObject.get(name);
    }
}

创建一个对象

package com;
/**
 * 创建一个对象后面在交给Bean
 * */
public class Hello {
    public void hi(){
        System.out.println("你好,springIOC");
    }

}

测试类

package cn.tedu.spring;

import cn.tedu.design.SpringContext;
import cn.tedu.pojo.Hello;

public class TestMyIOC {
	public static void main(String[] args) throws Exception {
		SpringContext spring = new SpringContext();
		Hello o = (Hello)spring.getBean("hello");
		System.out.println(o);//cn.tedu.pojo.Hello@6d06d69c
		o.hi();
	}
}

模拟SpringDI的底层实现

自定义注解模拟Spring中的@Autowired注解

package com.di;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//注解只能加载属性上
@Target(ElementType.FIELD)
//设置运行时有效,需要动态注入
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAutowired {
    String value() default "";
}

创建一个Teacher类用来向其他对象注入

package com.di;

import org.springframework.stereotype.Component;

@Component
public class Teacher {
    private String name = "韩梅梅";

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                '}';
    }
}

创建一个Student类需要将Teacher注入到Student对象中

package com.di;

import org.springframework.stereotype.Component;

@Component
public class Student {
    private String name="李雷";

    //使用自定义注解标记注入对象
    @MyAutowired
    private Teacher teacher;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", teacher=" + teacher +
                '}';
    }
}

创建一个测试类实现对象的注入,

package com.di;

import org.junit.Test;

import java.lang.reflect.Field;

public class TestDI {
    @Test

    public void di() throws Exception {
        //通过反射获取对象
        Class s = Class.forName("com.di.Student");
        //创建一个对象
        Object o = s.newInstance();
        //获取对象全部属性
        Field[] fs = s.getDeclaredFields();
        //遍历对象属性,拿到每一个属性
        for (Field f : fs) {
            //获取student中的注解
            MyAutowired an = f.getAnnotation(MyAutowired.class);
            //判断注解是否为空
            if(an != null){
                //需要将Teacher对象注入
                f.setAccessible(true);
                f.set(o,new Teacher());
            }
        }
        System.out.println((Student)o);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欧冶渃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值