Spring 反射实现容器IOC->DI

简单来说就是当自己需要一个对象的时候不需要自己手动去new一个,而是由其他容器来帮你提供;Spring里面就是IOC容器。

例如:

在Spring里面经常需要在Service这个装配一个Dao,一般是使用@Autowired 等注解:

 

首先遍历指定的包名:

 

 1、调用构造方法自动初始化 

 2、jdom2读取配置bean.xml,

 3、通过读取配置的bean.xml反射实例化读取的配置文件中的类和service;

 

 

Spring 反射实现容器IOC->DI

 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

[email protected]

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

[email protected]

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

[email protected]

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;

 [email protected]

------------------------------------------------------*/

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