目录
1 反射机制
就是正在运行动态获取当前类的所有信息,类可以不用new,使用Java反射机制帮你初始化。类的私有属性也可以用Java的反射机制赋值。需要核心当前类的字节码clas文件。
1.1反射机制的作用
1. 反编译:.class-->.java
2. 通过反射机制访问java对象的属性,方法,构造方法等;
3.提高程序的扩展性,封装一些工具、框架
1.3 反射机制的应用场景
Jdbc 加载驱动,Spring ioc框架
1.4 反射机制获取类有三种方法
//第一种方式: Classc1 = Class.forName("Employee"); //第二种方式: //java中每个类型都有class 属性. Classc2 = Employee.class;
//第三种方式: //java语言中任何一个java对象都有getClass 方法 Employeee = new Employee(); Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee) |
1.5 反射创建对象的方式
Class<?> forName = Class.forName("...User"); // 创建此Class 对象所表示的类的一个新实例 调用了User的无参数构造方法. Object newInstance = forName.newInstance(); |
实例化有参构造函数
Class<?> forName = Class.forName("...User"); Constructor<?> constructor = forName.getConstructor(String.class, String.class); User newInstance = (User) constructor.newInstance("123", "123"); |
1.6 禁止使用反射机制初始化
将构造函数为私有化。
1.7 反射创建api
方法名称 | 作用 |
getDeclaredMethods [] | 获取该类的所有方法 |
getReturnType() | 获取该类的返回值 |
getParameterTypes() | 获取传入参数 |
getDeclaredFields() | 获取该类的所有字段 |
setAccessible | 允许访问私有成员 |
1.8 样例
public class PrivateAttribute {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
//1、使用Java的反射机子 获取类的所有属性 方法 并且为私有属性赋值
Class<?> aClass = Class.forName("com.ilose.reflect.User");
//2、获取当前类的所有属性
Field[] fields=aClass.getDeclaredFields();
for (Field field :fields) {
System.out.println(field.getName());
}
//3、获取当前类的所有方法
Method[] methods=aClass.getDeclaredMethods();
for (Method method:methods) {
System.out.println(method.getName());
}
//4、使用Java的反射机制给私有属性赋值
Object o = aClass.newInstance();
Field id = aClass.getDeclaredField("id");
//允许反射操作私有属性
id.setAccessible(true);
id.set(o,"20");
Field name = aClass.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"losemyfuture");
User user= (User) o;
System.out.println(user.toString());
}
}
1.9 手写spring IOC
spring IOC就是把么一个bean(实体类)与bean(实体类)之间的关系都交给第三方容器管理
1.利用传入的参数获取xml文件的流,并且利用dom4j解析成Document对象
2.对于Document对象获取根元素对象<beans>后对下面的<bean>标签进行遍历,判断是否有符合的id.
3.如果找到对应的id,相当于找到了一个Element元素,开始创建对象,先获取class属性,根据属性值利用反射建立对象.
4.遍历<bean>标签下的property标签,并对属性赋值.注意,需要单独处理int,float类型的属性.因为在xml配置中这些属性都是以字符串的形式来配置的,因此需要额外处理.
5.如果属性property标签有ref属性,说明某个属性的值是一个对象,那么根据id(ref属性的值)去获取ref对应的对象,再给属性赋值.
6.返回建立的对象,如果没有对应的id,或者<beans>下没有子标签都会返回null
添加依赖:
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
</dependencies>
Java代码:
User.java
@Data
public class User{
public User() {
System.out.println("无参构造");
}
private String id;
private String name;
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
ClassPathXmlApplicationContext.java
public class ClassPathXmlApplicationContext {
private 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){
this.PATH=path;
init();
}
public Object getBean(String beanId) throws DocumentException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//1、解析xml
if(StringUtils.isEmpty(beanId)){
return null;
}
Object o=null;
SAXReader saxReader=new SAXReader();
Document read=saxReader.read(this.getClass().getClassLoader().getResource(PATH));
Element rootElement=read.getRootElement();
List<Element> elements = rootElement.elements();
for (Element element :elements) {
String id = element.attributeValue(ID);
if(!beanId.equals(id)){
//结束本次循环
continue;
}
//2、使用beanid查找xml结点,获取class节点属性
//获取配置文件中的bean
String attClass = element.attributeValue(CLASS);
//3、使用Java反射机制初始化类
Class<?> aClass = Class.forName(attClass);
o = aClass.newInstance();
//获取属性值
List<Element> elements1 = element.elements();
for (Element sonEle:elements1) {
//4、使用Java的反射机制私有化属性赋值
String attrField = sonEle.attributeValue(NAME);
String attrFieldValue = sonEle.attributeValue(VALUE);
Field declaredField = aClass.getDeclaredField(attrField);
declaredField.setAccessible(true);
declaredField.set(o,attrFieldValue);
}
}
return o;
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, DocumentException, IllegalAccessException {
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = (User) classPathXmlApplicationContext.getBean("user1");
System.out.println(user1.toString());
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="user1" class="com.ilose.reflect.User">
<property name="id" value="0002"></property>
<property name="name" value="张三"></property>
</bean>
<bean id="user2" class="com.ilose.reflect.User">
<property name="id" value="0003"></property>
<property name="name" value="蚂蚁课堂"></property>
</bean>
</beans>
输出:
无参构造
User{id='0002', name='张三'}