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);
// O=com.spring.service.UserService@1786e64
// beanObject====com.spring.dao.impl.UserDAOImpl@1c1ea29

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 Save...com.spring.model.User@f6a746

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=== com.spring.dao.impl.UserDAOImpl@fec107

T1null

T2[]

內循環次數======1

id=== userService

clazz===   com.spring.service.UserService

id:clazz   userService:com.spring.service.UserService

O=== com.spring.service.UserService@1617189

T1[Element: <property/>]

T2[[Element: <property/>]]

內循環次數======2

beanObject====com.spring.dao.impl.UserDAOImpl@fec107

T4 method name=setUserDAO

獲取第一個類方法 method==  public void com.spring.service.UserService.setUserDAO(com.spring.dao.UserDAO)

 

key = u, value = com.spring.dao.impl.UserDAOImpl@fec107

key = userService, value = com.spring.service.UserService@1617189

調用DAO層 DB Save...

調用DAO層 DB Save...com.spring.model.User@64f6cd

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=== com.spring.dao.impl.UserDAOImpl@872380

T1null

T2[]

內循環次數======1

id=== userService

clazz===   com.spring.service.UserService

id:clazz   userService:com.spring.service.UserService

O=== com.spring.service.UserService@2bb514

T1[Element: <property/>]

T2[[Element: <property/>]]

內循環次數======2

beanObject====com.spring.dao.impl.UserDAOImpl@872380

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=== com.spring.dao.impl.UserDAOImpl@16fa474

T1null

T2[]

內循環次數======1

id=== userService

clazz===   com.spring.service.UserService

id:clazz   userService:com.spring.service.UserService

O=== com.spring.service.UserService@95c083

T1[Element: <property/>]

T2[[Element: <property/>]]

內循環次數======2

beanObject====com.spring.dao.impl.UserDAOImpl@16fa474

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;

 factory=com.spring.ClassPathXmlApplicationContext@191d8c1

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

key = u, value = com.spring.dao.impl.UserDAOImpl@16fa474

key = userService, value = com.spring.service.UserService@95c083

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

該操作在Spring中通過注入方式DI實現  @Autowired private UserService userService; 

1、當編譯生成class字節碼時spring掃描配置文件中設置的java包文件;

2、讀取文件內容生成相關預加載xml;

3、當項目啓動時進行實例化

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

調用DAO層 DB Save...

調用DAO層 DB Save...com.spring.model.User@2d9c06

2989062 : 2989062 : {"id":0}

 

Process finished with exit code 0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章