0.前言 使用spring有什么优势和为什么我们要使用spring
0.1 Spring 两大特性 IoC(控制反转)/ DI(依赖注⼊) AOP(⾯向切⾯编程)
在学习软件开发基础的时候,我常常不懂老师为什么要强调使用IOC容器,我直接创建他不香吗?
1.如何使用IOC
1.1创建maven工程,并添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
现在pom.xml中注入依赖,分别注入springframework和lombok,lombok便于日后创造get set方法和自动重写toString方法,较为便捷
1.2创建实体类Student
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {
private int age;
private String name;
private long id;
private Address address;
}
@Data指的是为该类提供读写方法
@AllArgsConstructor;@NoArgsConstructor则是有参和无参构造
合理利用Lombok能够减少低效率的代码
1.3 传统的手动new对象
Student student = new Student();
student.setId(1);
student.setName("张三");
student.setAge(22);
System.out.println(student);
1.4建立spring.xml 能够实现元素的解耦合,将属性放置在xml文件中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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-3.0.xsd">
<bean id="student" class="Student">
<property name="id" value="20"></property>
<property name="age" value="1666"></property>
<property name="name" value="zhangsan"></property>
<property name="address" ref="address"></property>
</bean>
</beans>
1.5从 IoC 中获取对象,通过 id 获取
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
Student student = (Student) applicationContext.getBean("student");
System.out.println(student);
运行时发现,ClassPathXmlApplicationContext中要填写完整路径名称
2.通过dom4j来重现spring IOC的底层原理
2.1在maven中注入依赖dom4j
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.1</version>
</dependency>
2.2
package com.southwind.ioc;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.lang.reflect.Constructor;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class ClassPathXmlApplicationContext implements ApplicationContext {
private Map<String,Object> ioc = new HashMap<String, Object>();
public ClassPathXmlApplicationContext(String path){
try {
SAXReader reader = new SAXReader();
Document document = reader.read("./src/main/resources/"+path);
Element root = document.getRootElement();
Iterator<Element> iterator = root.elementIterator();
while(iterator.hasNext()){
Element element = iterator.next();
String id = element.attributeValue("id");
String className = element.attributeValue("class");
//通过反射机制创建对象
Class clazz = Class.forName(className);
//获取⽆参构造函数,创建⽬标对象
Constructor constructor = clazz.getConstructor();
Object object = constructor.newInstance();
//给⽬标对象赋值
Iterator<Element> beanIter = element.elementIterator();
while(beanIter.hasNext()){
Element property = beanIter.next();
String name = property.attributeValue("name");
String valueStr = property.attributeValue("value");
String ref = property.attributeValue("ref");
if(ref == null){
String methodName =
"set"+name.substring(0,1).toUpperCase()+name.substring(1);
Field field = clazz.getDeclaredField(name);
Method method =
clazz.getDeclaredMethod(methodName,field.getType());
//根据成员变量的数据类型将 value 进⾏转换
Object value = null;
if(field.getType().getName() == "long"){
value = Long.parseLong(valueStr);
}
if(field.getType().getName() == "java.lang.String"){
value = valueStr;
}
if(field.getType().getName() == "int"){
value = Integer.parseInt(valueStr);
}
method.invoke(object,value);通过运⾏时类获取 bean
这种⽅式存在⼀个问题,配置⽂件中⼀个数据类型的对象只能有⼀个实例,否则会抛出异常,因为没有
唯⼀的 bean。
通过有参构造创建 bean
在实体类中创建对应的有参构造函数。
配置⽂件
}
ioc.put(id,object);
}
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e){
e.printStackTrace();
} catch (NoSuchMethodException e){
e.printStackTrace();
} catch (InstantiationException e){
e.printStackTrace();
} catch (IllegalAccessException e){
e.printStackTrace();
} catch (InvocationTargetException e){
e.printStackTrace();
} catch (NoSuchFieldException e){
e.printStackTrace();
}
}
public Object getBean(String id) {
return ioc.get(id);
}
}