闭关修炼(八)反射机制
生活随笔
收集整理的這篇文章主要介紹了
闭关修炼(八)反射机制
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 反射
- 什么是反射機制?
- 反射機制的作用
- 通過java反射機制創建對象例子
- 使用默認無參構造函數創建對象
- 使用有參構造函數創建對象
- 怎么禁止反射機制?
- spring中的運用場景
- jdbc中的運用場景
- 使用反射機制訪問方法和屬性
- 訪問屬性
- 訪問方法
- 給私有屬性賦值
- 乞丐版springIOC實現
- 什么是springIOC?
- springioc過程
- springioc創建對象
- 實現思路
- 實現
反射
什么是反射機制?
反射機制就是正在運行(的程序中)動態獲取類的所有信息。
反射機制的作用
反編譯:.class -> .java。
通過反射機制訪問對象屬性,方法,構造方法等。
使用java反射機制可以不用new來初始化類。
類私有屬性可以通過java反射機制賦值。
提高程序的擴展性,封裝一些工具類,寫框架都會用到反射機制。
通過java反射機制創建對象例子
初始化類使用new創建對象,現在用反射機制來創建對象。
使用默認無參構造函數創建對象
package ch8;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.SneakyThrows;@Data @AllArgsConstructor @NoArgsConstructor class User{private String username;private String password; } public class Test1 {@SneakyThrowspublic static void main(String[] args) {// forName中寫類的完整路徑,即包名+類名Class<?> aClass = Class.forName("ch8.User");// 使用默認無參構造函數創建對象User user = (User) aClass.newInstance();System.out.println(user);} }使用有參構造函數創建對象
package ch8;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.SneakyThrows;import java.lang.reflect.Constructor;@Data @AllArgsConstructor @NoArgsConstructor class User{private String username;private String password; } public class Test1 {@SneakyThrowspublic static void main(String[] args) {/*// forName中寫類的完整路徑,即包名+類名Class<?> aClass = Class.forName("ch8.User");// 使用默認無參構造函數創建對象User user = (User) aClass.newInstance();System.out.println(user);*/// forName中寫類的完整路徑,即包名+類名Class<?> aClass = Class.forName("ch8.User");// 使用getConstructor獲取有參構造函數// 參數傳入有參構造函數的參數類型Constructor<?> constructor = aClass.getConstructor(String.class, String.class);// 創建對象User user2 = (User) constructor.newInstance("jack", "123");System.out.println(user2);} }怎么禁止反射機制?
把構造函數改成private修飾,但是反射還是能通過設置訪問權限禁止禁止反射
spring中的運用場景
寫標簽的時候經常遇到類似下面的格式
<bean id=“user” class=“com.java.bean.User”>
class值寫類的reference path,目的之一就是通過反射機制實例化對象
springIoc
jdbc中的運用場景
在加載jdbc驅動類的時候我們會寫:
class.forNmae(“com.mysql.jdbc.Driver”)
使用反射機制訪問方法和屬性
訪問屬性
package ch8;import java.lang.reflect.Field;public class Test2 {public static void main(String[] args) throws ClassNotFoundException {// 獲取類的字節碼文件Class<?> aClass = Class.forName("ch8.User");// 獲取當前類的所有屬性Field[] declaredFields = aClass.getDeclaredFields();// 遍歷for (Field field : declaredFields) {// 打印名稱System.out.println(field.getName());}} }訪問方法
package ch8;import java.lang.reflect.Field; import java.lang.reflect.Method;public class Test2 {public static void main(String[] args) throws ClassNotFoundException {// 獲取類的字節碼文件Class<?> aClass = Class.forName("ch8.User");// 獲取類的所有方法Method[] declaredMethods = aClass.getDeclaredMethods();// 遍歷輸出for (Method m : declaredMethods){System.out.println(m.getName());}} }給私有屬性賦值
package ch8;import java.lang.reflect.Field; import java.lang.reflect.Method;public class Test2 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {// 獲取類的字節碼文件Class<?> aClass = Class.forName("ch8.User");// 實例化對象User user = (User) aClass.newInstance();// 獲取屬性Field username = aClass.getDeclaredField("username");// 設置權限,允許操作私有屬性username.setAccessible(true);// 屬性賦值,第一個參數是類的對象, 第二個參數是賦的值username.set(user, "likeghee");// 獲取屬性Field password = aClass.getDeclaredField("password");// 設置權限password.setAccessible(true);// 屬性賦值password.set(user, "1234");// 打印System.out.println(user);} }乞丐版springIOC實現
什么是springIOC?
控制反轉,將bean與bean之間的關系交給第三方容器進行管理,不用自己手動創建對象。
springioc過程
加載springxml配置文件
傳入beanid獲取bean對象
springioc創建對象
使用無參構造函數
實現思路
實現
新建一個Context.xml放到resources文件夾下,模擬spring.xml
<?xml version="1.0" encoding="UTF-8"?> <beans><bean id="user1" class="myspringioc.User"><property name="username" value="ghee"/><property name="password" value="123"/></bean> </beans>新建ClassPathXmlApplicationContext類,實現它的getBean方法
package myspringioc;import lombok.SneakyThrows; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader;import java.lang.reflect.Field; import java.util.List;public class ClassPathXmlApplicationContext {private static String PATH;private static String ID;private static String CLASS;private static String NAME;private static String VALUE;public void init() {ID = "id";CLASS = "class";NAME = "name";VALUE = "value";}// 構造函數public ClassPathXmlApplicationContext(String path) {PATH = path;}@SneakyThrowspublic Object getBean(String id) {init();/*1. 用dom4j解析xml2. 通過beanid查找對應的xml節點,獲取class節點屬性3. 使用java反射機制newInstance類4. 使用java的反射機制給類屬性賦值*/if (id.equals("")) {return null;}SAXReader saxReader = new SAXReader();// 讀取resources下的配置文件Document read = saxReader.read(this.getClass().getClassLoader().getResource(PATH));// 遍歷二級節點,查詢beanid// 獲取根節點Element rootElement = read.getRootElement();// 獲取二級節點List<Element> elements = rootElement.elements();// 遍歷查找for (Element e : elements) {// 獲取id屬性的值String beanId = e.attributeValue(ID);// 如果和傳入的id相等,找到beanif (!beanId.equals(id)) {// 如果不相等就跳出本次循環continue;}// 找到了beanid// 獲取class屬性值,也就是包PTAHString attClassPath = e.attributeValue(CLASS);// 初始化beanClass<?> aClass = Class.forName(attClassPath);Object classObj = aClass.newInstance();// 獲取三級節點List<Element> propertyList = e.elements();for(Element property: propertyList){// 獲取name屬性的值String attNameValue = property.attributeValue(NAME);// 通過反射找到類中的屬性Field declaredField = aClass.getDeclaredField(attNameValue);// 獲取value屬性的值String attValueValue = property.attributeValue(VALUE);// 設置訪問權限declaredField.setAccessible(true);// 類屬性賦值declaredField.set(classObj, attValueValue);}return classObj;}return null;}}測試代碼
package myspringioc;public class Test {public static void main(String[] args) {ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("Context.xml");User user1 = (User) classPathXmlApplicationContext.getBean("user1");System.out.println(user1);} }乞丐版ioc實現成功了
使用方便,但是初始化對象效率很低。
總結
以上是生活随笔為你收集整理的闭关修炼(八)反射机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一分钟了解DMZ主机
- 下一篇: 【考研英语语法】状语从句精讲