前言
Spring IOC 管制反转是通过反射机制与工厂模式的联合,上面给大家模仿一下
生存案例引入
2000 年,你们家开了一家叫“笑笑”的包子铺 —— 爸
2002 年,你们城东新开了一家分店“笑笑”包子铺 —— 妈
2004 年,你们城西也新开了一家分店 ” 笑笑 ” 包子铺 —– 你
…
多年后,包子铺越开越多,口味难以保障
…
“笑笑”包子铺老板:当前咱们几个外围班子只在一家做包子,所有分店不在做包子,间接来咱们这里提货即可
带来的益处:
1、所有包子铺的口味统一
2、所有包子铺不在关注做包子,只卖,做包子的过程(管制权限)–某一个工厂外面—IOC(Spring 的管制反转)——> 工厂模式
代码案例
构建污浊类
public class Book {
private String name;
private String author;
private double price;
public Book (){}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public String getAuthor() {return author;}
public void setAuthor(String author) {this.author = author;}
public double getPrice() {return price;}
public void setPrice(double price) {this.price = price;}
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
}
class AB extends Book{}
class AC extends Book{}
传统形式构建实例
//1、传统形式
// 弊病:须要本人构建对象(new), 若我的项目中有几百个类,通过该形式构建实例不可取
Book b1 = new AB();
Book b2 = new AC();
污浊类的工厂类 BookFactory
public class BookFactory {
// 应用简略反射降级
public static Book getBook1() throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1、先应用反射获取 Book 的 Class 对象
Properties pro = new Properties();
//2、获取配置文件信息,加载配置文件
pro.load(new FileInputStream("D://JavaServletProject//ServletDemo//ZhenAiDemoVersionTwo//src//org//soffteem//sources//book//book.properties"));
//3、失去配置文件外面的 key 值,依据 key 值反射失去 class 对象
Class<Book> bookClass = (Class<Book>)Class.forName(pro.getProperty("className"));
//4、获取有参结构器
Constructor<Book> cons = bookClass.getDeclaredConstructor(String.class,String.class,double.class);
//5、通过反射构建对象实例
return cons.newInstance(pro.getProperty("name"),pro.getProperty("author"),Double.parseDouble(pro.getProperty("price")));
}
// 如果用户过去须要书,会依据类名去构建书对象,原始办法
public static Book getBook(String name){
Book book = null;
if (name.equals("AB")){b = new AB();
}else if (name.equals("AC")){b = new AC();
}else {//.... 如果有很多的书籍屡次断定.....}
return book;
}
}
传统形式上降级
//2、当初有了笑笑包子铺(污浊类工厂)
// 弊病:此时不须要构建对象,然而仍然须要手动输出对象名称
System.out.println("请您输出须要的书名");
//.... 此处省略局部代码......
Book book = BookFactory.getBook("你输出的名字");
通过简略反射降级
className=org.soffteem.myspring.Book
author= 王大锤
name= 倚天屠龙记
price=38.9
//3、不必输出就能构建对象
// 弊病:如果不是 Book 对象而是其余对象呐?调用该工厂的这个办法只可能返回 Book 对象
System.out.println("获取书籍:" + BookFactory.getBook1());
相似 Spring IOC 容器的工厂构建
XML 文件
<?xml version="1.0" encoding="utf-8" ?>
<beans>
<!-- 书籍类 -->
<bean id="book" class="org.soffteem.myspring.Book">
<property name="name" value="倚天屠龙记"></property>
<property name="author" value="金庸"></property>
<property name="price" value="25.3"></property>
</bean>
<!-- 各种其余类 -->
<!-- 此处的 student 类没有展现 -->
<bean id="student" class="org.soffteem.test.Student"></bean>
</beans>
相似 ”Spring IOC 容器 ” 类
public class ApplicationContextUtils {
// 文档对象
Document document;
//1、初始化文档对象
public ApplicationContextUtils() throws DocumentException {
//1.1 通过 dom4j 的 jar 读取 xml 文件,获取文档对象
SAXReader reader = new SAXReader();
this.document = reader.read("D://JavaServletProject//ServletDemo//ZhenAiDemoVersionTwo//src//org//soffteem//sources//book//books.xml");
}
//2、反射 + 汇合 + xml 解析 获取 Bean 实例
public <T>T getBean(String id,Class<T> tc) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//2.1 解析 xml 文件,获取根节点 <beans><beans>
Element element = document.getRootElement();
//2.2 获取根节点 (<beans>) 所有的子节点 <bean></bean>
List<Element> list = element.elements();
//3、迭代所有的 <bean> 节点
for (Element e:list){
//3.1 失去 <bean> 子节点中 id 的值
String myId = e.attributeValue("id");
//3.2 失去 <bean> 子节点中 class 的数值
String className = e.attributeValue("class");
//3.3 断定: 依据用户输出的 id 进行指定的实例化
// 因为此处可能不只只有一个污浊类的节点配置项,要依据用户输出的 id 值实例化执行的配置节点
if (myId.equals(id)){
//3.3.1 反射以后 id 对应的 className 的 class 对象
Class c = Class.forName(className);
//3.3.2 再次断定:若是父类呐?此处判断父类我是通过 class 对象断定的
if (c == tc){
//3.3.3 通过反射构建对象
T obj = tc.newInstance();
//3.3.4 失去以后 <bean> 节点中的所有 <properties> 子节点
List<Element> props = e.elements();
//3.3.5 失去所有的孙子节点对象 <properties>
for (Element prop:props){
//3.3.5.1 失去孙子节点的每一个属性内容 name 与 value 对应的值
String name = prop.attributeValue("name");
String value = prop.attributeValue("value");
//3.3.5.2 将内容赋值到对象属性中
setAttribute(tc.getDeclaredFields(),obj,name,value);
}
// 返回对象
return obj;
}
}
}
return null;
}
// 封装给属性赋值的办法
//① 须要失去所有的属性 ② 给哪个对象赋值 ③ 给哪个属性赋值 ④赋值的内容
public <T>void setAttribute(Field[] fields,T obj,String key,String value) throws IllegalAccessException {
//1、循环属性,失去具体的属性值
for (Field field:fields){
//2、要想给属性赋值,因为属性是公有的,须要设置属性的拜访权限
field.setAccessible(true);
//3、考虑一下属性的类型:根本属性类型、对象类型
Class type = field.getType();// 获取以后属性字段 field 的类型
// 此处我只写了几个根本数据类型,其余类型可自行添加......
if (key.equals(field.getName())){if (type == int.class){field.set(obj,Integer.parseInt(value));
}else if (type == double.class){field.set(obj,Double.parseDouble(value));
}else if (type == String.class){field.set(obj,value);
}else {
// 若是对象类型
field.set(obj,value);
}
}
}
}
}
模仿 ”Spring 容器 ” 构建实例
//1、构建 "Spring 容器" 最先实例化可通过 on-load-startup 属性, 前期交给 tomcat 容器
ApplicationContextUtils application = new ApplicationContextUtils();
//2、通过 "Spring 容器" 联合配置文件的 Id 属性值获取 Book 对象
Book book = application.getBean("book",Book.class);
//3、格式化输入对象,进行内容展现
System.out.println(book.toString());
模仿 ”Spring 容器 ” 构建实例步骤总结
- 构建污浊类,也就是 JavaBean 类
- 构建工厂类,便于 JavaBean 通过工厂创立实例
- 实例化工厂,调用工厂类的办法获取实例对象
- Spring IOC 获取实例步骤总结
- 构建污浊类
- 构建 Spring 框架的配置文件
- 将污浊类注入到配置文件中
- 实例化 Spring 容器,通过 getBean()办法依据 Id 属性值来获取对应的实例
最初
欢送关注公众号:前程有光,支付一线大厂 Java 面试题总结 + 各知识点学习思维导 + 一份 300 页 pdf 文档的 Java 外围知识点总结!这些材料的内容都是面试时面试官必问的知识点,篇章包含了很多知识点,其中包含了有基础知识、Java 汇合、JVM、多线程并发、spring 原理、微服务、Netty 与 RPC、Kafka、日记、设计模式、Java 算法、数据库、Zookeeper、分布式缓存、数据结构等等。