这篇博客主要是对spring的相关概念进行通俗易懂的解释,以及用自己的代码写一个spring简易容器,实现类似于spring的功能。
Ioc概念
Ioc(控制反转):原本我们创建一个对象是用new关键字,我们可以很明确的知道自己要创建一个什么样的对象,而现在我们把创建对象的工作交给了spring来处理。也就是我们把控制权交给了别人,spring返回什么东西我们是不知道的。
DI概念
指Spring创建对象的过程中,将对象依赖的属性(简单值,集合,对象)通过配置的方式进行设值。
写一个简易spring容器
首先,我们应该了解Ioc带来的好处,就是帮助项目降低耦合。
解耦思路:
1.使用反射来创建对象,避免使用new关键字。
2.通过读取配置文件来获取创建对象的全限定名。
根据上面的思路,我们来写一个简易容器。
一、定义几个我们常用的实体类
//Student类
public class Student {
private String name;
private Integer age;
public Student(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
//User类
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
二、定义枚举(用于判断单例模式和原型模式)
//SINGLETON代表单例模式,MORE代表原型模式,也就是多例
public enum Model{
SINGLETON,MORE;
}
三、application.properties核心配置文件
#把两个实体类的全限定名写入,类似于配置bean
user=pojo.User
student=pojo.Student
四、写核心类
我们使用spring容器时,是定义ApplicationContext来创建容器,那我们自己写一个类
MyApplicationContext。
public class MyApplicationContext {
//配置文件名字
private String propertiesName;
//定义map集合
private static Map<String,Object> map=new HashMap();
//带参数构造函数
public MyApplicationContext(String propertiesName){
this.propertiesName=propertiesName;
//读取配置文件
InputStream inputStream=TextProperties.class.getClassLoader().getResourceAsStream(propertiesName);
//创建properties对象
Properties properties=new Properties();
//关联文件
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
//获取配置文件中所有的key值
Set<Object> keys = properties.keySet();
Iterator<Object> iteratorKeys = keys.iterator();
//获取配置文件中所有的value
Collection<Object> values = properties.values();
Iterator<Object> iteratorValues = values.iterator();
//遍历,将bean的名字和对象保存进map集合,这样实现单例模式
while (iteratorKeys.hasNext()){
Class c = null;
try {
c = Class.forName((String) iteratorValues.next());
//利用反射创建对象
map.put((String)iteratorKeys.next(),c.newInstance());
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
//多实例创建对象,这样可以保证每次创建的对象都不是相同的
private Object createMore(String beanId)throws Exception{
//读取配置文件
InputStream inputStream=TextProperties.class.getClassLoader().getResourceAsStream(this.propertiesName);
//创建properties对象
Properties properties=new Properties();
//关联文件
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
String property = properties.getProperty(beanId);
Class c = Class.forName(property);
return c.newInstance();
}
//getBean方法,默认使用单实例
public Object getBean(String beanId)throws Exception{
return getBean(beanId,Model.SINGLETON);
}
//getBean重载方法,可以选择单例模式或者原型模式
public Object getBean(String beanId,Model e)throws Exception{
Object o="";
//switch进行选择
switch (e){
case SINGLETON:
o= map.get(beanId);
break;
case MORE:
o= this.createMore(beanId);
break;
}
return o;
}
}
测试
public static void main(String[] args)throws Exception {
MyApplicationContext myApplicationContext=new MyApplicationContext("application.properties");
User user =(User) myApplicationContext.getBean("user", Model.MORE);
User user1 = (User) myApplicationContext.getBean("user", Model.MORE);
User user2 =(User) myApplicationContext.getBean("user");
User user3 =(User) myApplicationContext.getBean("user");
System.out.println("单例模式,判断容器获取的对象是否为同一个:"+(user2==user3));
System.out.println("原型模式,判断容器获取的对象是否为同一个:"+(user==user1));
}
运行结果:
根据结果,我们写的容器简单实现了spring容器的一些功能。
包括选择创建单例模式还是原型模式。
扫描二维码关注公众号,回复:
11585075 查看本文章
欢迎大家一起讨论学习,学无止境加油!