反射是什么
1.反射是Java API,是Java提供的现成的类,是Java提供的功能.
2.反射是Java提供的动态执行机制,动态加载类,动态创建对象,动态访问属性,动态调用方法。
动态与静态
静态:事先约定的规则,执行期间按照固定的规则执行
动态:事先没有约定,在执行期间动态确定执行规则
Java中的静态执行:编译就已经确定执行规则(执行次序),在运行期间按照结果顺序执行,如:
Foo foo=new Foo();
foo.hello();
Java中的动态执行:运行期间才能确定加载哪些类,创建哪些对象,执行哪些方法
动态加载类
Java提供了动态加载类的API
Class cls=Class.forName(类名);
动态创建对象
cls.newInstance();
执行cls应用的类的信息中的无参构造器,动态创建实例,如果没有无参构造器,则抛异常。
反射可以调用有参构造器(复杂)
动态获取类的方法信息和动态执行方法
method.invoke(执行方法的对象,传递的参数)
必须在一个对象上执行一个非静态方法,调用方法时必须有对象
在invoke方法执行时,必须传递包含当前方法的对象
Object obj=method.invoke(对象,参数1,参数2,….);
invoke方法有返回值,返回被调用方法执行的结果,对象后面的参数是执行方法时候传递的参数
invoke可以调用私有方法,打破了封装
例子:
辅助方法类
```
//辅助方法类
package demo;
public class Foo {
public void test1(){
System.out.println("test1()");
}
public void test2(){
System.out.println("test2()");
}
public void test3(){
System.out.println("test3()");
}
private String demo(String name,int age){
return name+age;
}
}
测试类
//测试类
package demo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;
public class demo3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Scanner scan=new Scanner(System.in);
System.out.println(“请输入类名”);
String name=scan.nextLine();
Class cls=Class.forName(name);
//找到demo方法
//Class提供了根据方法的标签名找到方法的API
String methodName=”demo”;//方法名
//类型列表Class[]
//String.class表示字符串类型,int.class表示整型 ,任何.class表示任何类型
Class[] types={String.class,int.class};
//根据方法签名查找方法
Method method=cls.getDeclaredMethod(methodName, types);
//找到了私有方法
System.out.println(method);
//执行私有方法
//打开方法的执行权限!违反封装!
method.setAccessible(true);
Object obj=cls.newInstance();
Object value=method.invoke(obj, “tom”,12);
System.out.println(value);
}
}
# 反射用途
1.eclipse中解析类的结构使用了反射
2.JUnit识别被测试的方法使用了反射
2.1JUnit利用反射查找@Test开头的方法
2.2JUnit利用反射解析@Test标注的测试方法
3.spring管理bean对象,注入bean属性使用了反射
3.1利用反射创建bean实例
3.2利用发射注入bean属性
4.注解的解析使用了反射,利用反射API支持注解
5.强行执行私有方法,访问私有属性
# JUnit原型
原理:
![](https://i.imgur.com/aDntwhe.png)
//自己定义一个注解
package demo;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Demo {
}
测试方法
//测试方法
package demo;
/*
- 执行一个类中全部以@Demo标注的方法
*/
public class TestCase {
@Demo
public void Hello(){
}System.out.println("hello()");
@Demo
public void hi(){
}System.out.println("hi()");
public void test(){
}System.out.println("test()");
}
# spring原型
原理:
![](https://i.imgur.com/7HjCYae.png)
package demo;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class ApplicationContext {
//缓存spring容器中的bean对象
private Map
/*
* 利用配置文件初始化当前容器
* 利用XML,初始化全部bean对象
*/
public ApplicationContext(String xml) throws DocumentException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
//利用dom4j,读取想XML文件
//解析文件内容,得到bean id和bean类名
//根据类名动态加载列并创建对象,将对象和对应的id传到map中
//从Resource(classpath)中读取流
InputStream in=getClass().getClassLoader().getResourceAsStream(xml);
SAXReader reader=new SAXReader();
Document doc=reader.read(in);
in.close();
//解析XML<beans><bean><bean><bean>...
Element root=doc.getRootElement();
//读取根元素中全部bean子元素
List<Element> list=root.elements("bean");
for (Element e : list) {
//e 就是bean元素id属性和class属性
String id=e.attributeValue("id");
String className=e.attributeValue("class");
//动态加载类,动态创建对象
Class cls=Class.forName(className);
Object bean= cls.newInstance();
beans.put(id, bean);
}
}
public Object getBean(String id){
//根据id在map中查找对象,并返回对象
return beans.get(id);
}
//泛型方法,优点:可以减少一次类型转换
public<T> T getBean(String id,Class<T> cls){
return (T)beans.get(id);
}
}
一个测试的XML配置文件
<?xml version=”1.0” encoding=”UTF-8”?>
```