Spring 反射实现容器IOC->DI
简单来说就是当自己需要一个对象的时候不需要自己手动去new一个,而是由其他容器来帮你提供;Spring里面就是IOC容器。
例如:
在Spring里面经常需要在Service这个装配一个Dao,一般是使用@Autowired 等注解:
首先遍历指定的包名:
1、调用构造方法自动初始化
2、jdom2读取配置bean.xml,
3、通过读取配置的bean.xml反射实例化读取的配置文件中的类和service;
cmd
进入E 盘
E:
进入相关文件目录
cd /src/main/java/com/spring
tree /f
tree /f F:\...\src\main\java\com\spring
------------------------------------------com.spring 包下文件结构
│ beans.xml
│ ClassPathXmlApplicationContext.java
│ UserServiceTest.java
│
├─dao
│ │ UserDAO.java
│ │
│ └─impl
│ UserDAOImpl.java
│
├─model
│ User.java
│
├─service
│ UserService.java
│
└─spingmn
BeanFactory.java
/*-------------------------------------------------------------------------------------------------------------------*/
UserDAO.java
package com.spring.dao;
import com.spring.dao.impl.UserDAOImpl;
import com.yang.dao.UserDao;
/**
* Created by Neusoft on 2019/10/21.
*/
public interface UserDAO {
public UserDao save(Object o);
}
/*-------------------------------------------------------------------------------------------------------------------*/
//UserDAOImpl.java
package com.spring.dao.impl;
import com.spring.dao.UserDAO;
import com.yang.dao.UserDao;
/**
* Created by Neusoft on 2019/10/21.
*/
public class UserDAOImpl implements UserDAO {
@Override
public UserDao save(Object o) {
System.out.println("调用DAO层 Save...");
return null;
}
}
/*-------------------------------------------------------------------------------------------------------------------*/
//User.java
package com.spring.model;
/**
* Created by Neusoft on 2019/10/21.
*/
public class User {
private long id;
private String name;
private String PWD;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPWD() {
return PWD;
}
public void setPWD(String PWD) {
this.PWD = PWD;
}
}
/*-------------------------------------------------------------------------------------------------------------------*/
//UserService.java
package com.spring.service;
import com.spring.model.User;
import com.spring.dao.UserDAO;
/**
* Created by Neusoft on 2019/10/21.
*/
public class UserService {
private UserDAO userDAO;
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void add(User u){
this.userDAO.save(u);
}
}
/*-------------------------------------------------------------------------------------------------------------------*/
//BeanFactory.java 重点面向接口编程
package com.spring.spingmn;
/**
* Created by Neusoft on 2019/10/21.
*/
public interface BeanFactory {
public Object getBean(String name);
}
/*-------------------------------------------------------------------------------------------------------------------*/
//beans.xml
<beans>
<bean id="u" class="com.spring.dao.impl.UserDAOImpl"/>
<bean id="userService" class="com.spring.service.UserService">
<property name="userDAO" bean="u"/>
</bean>
</beans>
/*-------------------------------------------------------------------------------------------------------------------*/
//ClassPathXmlApplicationContext.java 用jdk反射实现xml 配置的类 IOC-》DI
package com.spring;
import com.spring.spingmn.BeanFactory;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import java.awt.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Created by Neusoft on 2019/10/21.
*/
public class ClassPathXmlApplicationContext implements BeanFactory{
private Map<String,Object> beans = new HashMap<String,Object>();
public ClassPathXmlApplicationContext() throws Exception {
System.out.println("jdom2 解析xml文件 :\n");
//创建一个解析器
SAXBuilder saxBuilder = new SAXBuilder();
//将流加载到解析器中。
//Document document = saxBuilder.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
Document document = saxBuilder.build(this.getClass().getResource("").getPath()+"beans.xml"); //可能需手动将文件放入class 文件夹
//获取文档的根节点
Element root=document.getRootElement();
//将根节点的所有子节点获取放到一个集合中
List list=root.getChildren("bean");
//循环遍历所有子节点
System.out.println("外循环次数======"+(list.size()+1));
for (int i = 0; i < list.size(); i++) {
Element element=(Element)list.get(i);
String id=element.getAttributeValue("id");
String clazz=element.getAttributeValue("class");
System.out.println("id=== "+id);
System.out.println("clazz=== "+clazz);
System.out.println("id:clazz "+id+":" +clazz);
/*
Class.forName(String className)这个方法传入一个类型的全路径的名字(也就是带包的完整名字),会返回一个字节码类型(也就是Class类型)的实例
如:Class clazz = Class.forName("com.dean.Person");
然后再用这个字节码类型的实例clazz调用newInstance()方法会返回一个Object类型的对象
这个object当然不能直接调用Perosn类的方法了,因为他是Object类型
这个时候就需要强制类型转换了
Person person = (Perosn)clazz.newInstance();
*/
Object O=Class.forName(clazz).newInstance();
System.out.println("O=== "+O);
beans.put(id,O); //放入map
System.out.println("T1"+element.getChild("property"));
System.out.println("T2"+element.getChildren("property"));
System.out.println("内循环次数======"+(element.getChildren("property").size()+1));
for (Element propertyElement:(List<Element>)element.getChildren("property")) {
String name = propertyElement.getAttributeValue("name"); //userDAO
String bean = propertyElement.getAttributeValue("bean"); //u
Object beanObject=beans.get(bean); //UserDaoImpl instance
System.out.println("beanObject===="+beanObject);
String methodName="set"+name.substring(0,1).toUpperCase()+name.substring(1);
System.out.println("T4 method name="+methodName);
//获得对象所声明的公开方法
//该方法的第一个参数name是要获得方法的名字,第二个参数parameterTypes是按声明顺序标识该方法形参类型
Method method=O.getClass().getMethod(methodName,beanObject.getClass().getInterfaces()[0]);
System.out.println("获取第一个类方法 method== "+method);
//传入要执行的实体类 和 执行的方法对应的参数 Object i = method.invoke(new AA(), 1,2);
Object omi = method.invoke(O,beanObject);
// [email protected]
// [email protected]
System.out.println();
}
}
}
@Override
public Object getBean(String name) {
//使用Iterator遍历
Iterator iter = beans.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
}
return beans.get(name);
}
public void readXML() throws Exception{
try {
//创建一个解析器
SAXBuilder builder=new SAXBuilder();
//创建一个文件输入流
InputStream in=new FileInputStream(this.getClass().getResource("").getPath()+"beans.xml");
//将流加载到解析器中。
Document document=builder.build(in);
//获取文档的根节点
Element rootElement=document.getRootElement();
//将根节点的所有子节点获取放到一个集合中
List<Element> list=rootElement.getChildren();
//循环遍历所有子节点
for(Element element:list){
System.out.println("开始遍历第"+(list.indexOf(element)+1)+"节点======");
//获取所有的属性并遍历输出
List<Attribute> list1=element.getAttributes();
for(Attribute attr:list1){
System.out.println("属性名是:"+attr.getName());
System.out.println("属性值是:"+attr.getValue());
}
System.out.println("结束遍历第"+(list.indexOf(element)+1)+"节点======");
}
}catch (IOException e){
//打印输出异常
e.printStackTrace();
}
finally{
System.out.println("如调试运行异常需将beans.xml复制到相关class 目录下");
}
}
}
/*-------------------------------------------------测试类------------------------------------------------------------------*/
//UserServiceTest.java
package com.spring;
import com.spring.dao.UserDAO;
import com.spring.dao.impl.UserDAOImpl;
import com.spring.model.User;
import com.spring.service.UserService;
import com.spring.spingmn.BeanFactory;
import org.junit.Test;
/**
* Created by Neusoft on 2019/10/21.
*/
public class UserServiceTest {
@Test
public void testAdd_old1() throws Exception {
System.out.println("当前执行方法 " + this.getClass().getSimpleName()+ ":" + new Exception().getStackTrace()[0].getMethodName());
UserService userService = new UserService(); //new 出服务
UserDAO userDAO = new UserDAOImpl(); //new DAO层实现
userService.setUserDAO(userDAO);
User user = new User();
userService.add(user);
}
@Test
public void testAdd_old2() throws Exception {
System.out.println("当前执行方法 " + this.getClass().getSimpleName()+ ":" + new Exception().getStackTrace()[0].getMethodName());
BeanFactory factory = new ClassPathXmlApplicationContext();
UserService userService = new UserService();
UserDAO userDAO = (UserDAO) factory.getBean("u");
userService.setUserDAO(userDAO);
User user = new User();
userService.add(user);
}
@Test
public void testAddSpringMN() throws Exception {
System.out.println("当前执行方法 " + this.getClass().getSimpleName()+ ":" + new Exception().getStackTrace()[0].getMethodName());
BeanFactory factory = new ClassPathXmlApplicationContext();
System.out.println("/*------------------------------------------------------");
System.out.println(" 1、调用构造方法自动初始化 \n 2、jdom2读取配置bean.xml,\n 3、通过读取配置的bean.xml反射实例化读取的配置文件中的类和service;\n factory=" + factory);
System.out.println("------------------------------------------------------*/");
UserService userService = (UserService) factory.getBean("userService");//该操作在Spring中通过注入方式DI实现 @Autowired private UserService userService; 当编译生成class字节码时spring扫描配置文件中设置的java包文件,读取文件内容生成相关预加载xml,当项目启动时进行实例化
System.out.println("/*------------------------------------------------------");
System.out.println("该操作在Spring中通过注入方式DI实现 @Autowired private UserService userService; \n1、当编译生成class字节码时spring扫描配置文件中设置的java包文件;\n2、读取文件内容生成相关预加载xml;\n3、当项目启动时进行实例化");
System.out.println("------------------------------------------------------*/");
User user = new User();
userService.add(user);
}
@Test
public void readXMLText() throws Exception {
System.out.println("当前执行方法 " + this.getClass().getSimpleName()+ ":" + new Exception().getStackTrace()[0].getMethodName());
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext();
classPathXmlApplicationContext.readXML();
}
}
/*---------------------------------------执行测试类结果-----------------------------------------*/
/*---------------------------------------执行测试类结果-----------------------------------------*/
/*---------------------------------------执行测试类结果-----------------------------------------*/
/*---------------------------------------执行测试类结果-----------------------------------------*/
"D:\Program Files\jdk1.6.0_43\bin\java" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA
....com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 com.spring.UserServiceTest
当前执行方法 UserServiceTest:testAdd_old1
调用DAO层 DB Save...
调用DAO层 DB [email protected]
16164678 : 16164678 : {"id":0}
当前执行方法 UserServiceTest:testAdd_old2
jdom2 解析xml文件 :
外循环次数======3
id=== u
clazz=== com.spring.dao.impl.UserDAOImpl
id:clazz u:com.spring.dao.impl.UserDAOImpl
O=== [email protected]
T1null
T2[]
内循环次数======1
id=== userService
clazz=== com.spring.service.UserService
id:clazz userService:com.spring.service.UserService
O=== [email protected]
T1[Element: <property/>]
T2[[Element: <property/>]]
内循环次数======2
T4 method name=setUserDAO
获取第一个类方法 method== public void com.spring.service.UserService.setUserDAO(com.spring.dao.UserDAO)
key = u, value = [email protected]
key = userService, value = [email protected]
调用DAO层 DB Save...
调用DAO层 DB [email protected]
6616781 : 6616781 : {"id":0}
当前执行方法 UserServiceTest:readXMLText
jdom2 解析xml文件 :
外循环次数======3
id=== u
clazz=== com.spring.dao.impl.UserDAOImpl
id:clazz u:com.spring.dao.impl.UserDAOImpl
O=== [email protected]
T1null
T2[]
内循环次数======1
id=== userService
clazz=== com.spring.service.UserService
id:clazz userService:com.spring.service.UserService
O=== [email protected]
T1[Element: <property/>]
T2[[Element: <property/>]]
内循环次数======2
T4 method name=setUserDAO
获取第一个类方法 method== public void com.spring.service.UserService.setUserDAO(com.spring.dao.UserDAO)
开始遍历第1节点======
属性名是:id
属性值是:u
属性名是:class
属性值是:com.spring.dao.impl.UserDAOImpl
结束遍历第1节点======
开始遍历第2节点======
属性名是:id
属性值是:userService
属性名是:class
属性值是:com.spring.service.UserService
结束遍历第2节点======
如调试运行异常需将beans.xml复制到相关class 目录下
当前执行方法 UserServiceTest:testAddSpringMN
jdom2 解析xml文件 :
外循环次数======3
id=== u
clazz=== com.spring.dao.impl.UserDAOImpl
id:clazz u:com.spring.dao.impl.UserDAOImpl
O=== [email protected]
T1null
T2[]
内循环次数======1
id=== userService
clazz=== com.spring.service.UserService
id:clazz userService:com.spring.service.UserService
O=== [email protected]
T1[Element: <property/>]
T2[[Element: <property/>]]
内循环次数======2
T4 method name=setUserDAO
获取第一个类方法 method== public void com.spring.service.UserService.setUserDAO(com.spring.dao.UserDAO)
/*------------------------------------------------------
1、调用构造方法自动初始化
2、jdom2读取配置bean.xml,
3、通过读取配置的bean.xml反射实例化读取的配置文件中的类和service;
------------------------------------------------------*/
key = u, value = [email protected]
key = userService, value = [email protected]
/*------------------------------------------------------
该操作在Spring中通过注入方式DI实现 @Autowired private UserService userService;
1、当编译生成class字节码时spring扫描配置文件中设置的java包文件;
2、读取文件内容生成相关预加载xml;
3、当项目启动时进行实例化
------------------------------------------------------*/
调用DAO层 DB Save...
调用DAO层 DB [email protected]
2989062 : 2989062 : {"id":0}
Process finished with exit code 0