一、反射

1、概述:

JAVA反射机制是在运行状态中,对于任意一个类,都能够创建该类对象,调用这个类的所有属性和方法包括构造方法;

2、字节码文件

1)概述:

类加载器负责将.class文件加载到内在中,并为之生成对应的Class对象

2)字节码文件对象的三种获取方式

A:Object类的getClass()方法

B:所有类包括基本数据类型的静态属性class

如:int.class; String.class

C:Class类中静态方法forName(String className) //参数:className - 所需类的完全限定名

3、Class类

1)获取构造器:

获取其类全部构造器:返回表示此类构造方法的 Constructor 对象数组

public Constructor[] getConstructors() //只能获取其公共构造器

public Constructor[] getDeclaredConstructors() //获取所有构造器包括私有

获取其类一个构造器:

参数:可变参数,参数数组,传入需要调用的构造器的参数的字节码文件(类型.class)

返回值:与指定的 parameterTypes 相匹配的构造方法的 Constructor 对象

public Constructor getConstructor(Class... parameterTypes) //只能获取其公共构造器

public Constructor getDeclaredConstructor(Class... parameterTypes) //获取所有构造器包括私有

通过获取的构造器调用newInstance(Object... initargs)方法就可以创建该类对象

通过Class类的public T newInstance()方法也可以用来创建该类的无参对象

2)获取属性

获取所有成员变量:返回表示字段的 Field 对象的数组

public Field[] getFields() //只能获取其公共属性

public Field[] getDeclaredFields() //获取所有属性

获取单个成员变量

参数:需要获取的属性的名称

返回值:由 name 指定的该类的 Field 对象

public Field getField(String name) //只能获取其公共属性

public Field getDeclaredField(String name) //获取所有属性

使用Field的public void set(Object obj,Object value)方法可以给该属性赋值

参数: obj:应该修改其字段的对象

value:正被修改的 obj 的字段的新值

3)获取成员方法

获取所有成员方法:表示此类中方法的 Method 对象的数组

public Method[] getMethods() //获取所有的共有的方法,包括父类的公共方法

public Method[] getDeclaredMethods() //获取所有的方法对象,包括私有的

获取单个成员方法

public Method getMethod(String name,Class... parameterTypes) //获取指定的方法对象

public Method getDeclaredMethod(String name,Class... parameterTypes) //获取包括私有的方法对象

使用Method的public Object invoke(Object obj,Object... args)调用方法

参数: obj:从中调用底层方法的对象

Object... args:该方法的参数

4、取消语法检查

1)AccessibleObject类 —— 是 Field、Method 和 Constructor 对象的基类

直接已知子类:Constructor, Field, Method 

2)public void setAccessible(boolean flag)throws SecurityException

当flag是true的时候则指示反射的对象在使用时应该取消 Java 语言访问检查

3)使用:

在使用反射创建类的私有化对象、给私有化属性赋值、调用私有化方法的时候,需要先调用此方法,取消语法检查;

就是执行newInstance()、set()、invoke()前调用setAccessible(true)

5、运行配置文件

import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Properties;
//通过反射运行配置文件内容
public class Test {
    public static void main(String[] args) throws Exception {
	//将配置文件读取到Properties集合中
	Properties pro = new Properties();
	pro.load(new FileInputStream("a.txt"));
	//通过键找值获取到需要创建对象的类的完全限定名,获取其字节码文件对象
	Class clazz = Class.forName(pro.getProperty("classname"));
	//通过键找值获取到需要调用的成员方法
	Method met = clazz.getMethod(pro.getProperty("methodname"));
	//执行
	met.invoke(clazz.newInstance());
    }
}
public class Student {
  public void show(){
        System.out.println("这是学生类的show方法");
  }
  public void method(){
	System.out.println("这是学生类的method方法");
    }
}
public class Teacher {
    public void show(){
	System.out.println("这是老师类的show方法");
    }
    public void method(){
	System.out.println("这是老师类的method方法");
    }
}

---------------------------------------------------------

当前项目下的a.txt配置文件

classname = 所需类的完全限定名

methodname = show

---------------------------------------------------------

需要修改时候只需改变其配置文件的值

6、越过泛型检查

import java.lang.reflect.Method;
import java.util.ArrayList;
public class ArrayListDemo {
    public static void main(String[] args) throws Exception{
	ArrayList al = new ArrayList();
	al.add("Hello");
	al.add("java");
	//想要加入一个int类型的数10
	//获取其字节码文件对象
	Class clazz = al.getClass();
	//调用add方法
	Method m = clazz.getMethod("add", Object.class);
	//取消语法检查
	m.setAccessible(true);
	//添加10,并遍历
	m.invoke(al, 10);
	for(Object o : al){
		System.out.println(o);
	}
    }
}

7、动态代理

1、概述:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象

在Java中提供了一个Proxy和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象

2、Proxy类 —— 生成代理对象JDK提供的代理只能针对接口做代理

public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)

// 参数1:类加载器 通过Class类的getClassLoader()调用

// 参数2:类加载器对应的接口数组 通过Class的getInterfaces()调用

// 参数3:你要让这个代理对象帮你干的事情

//返回值:可以强转成被代理类所实现的接口的对象,调用被代理的方法

//自定义一个类实现InvocationHandler接口,重写public Object invoke(Object proxy, Method method, Object[] args)方法

// 参数1:代理对象 Object proxy

// 参数2:被代理类里面的方法对象

// 参数3:被代理类里面的方法对象要的参数的值

//返回值:被代理类对象所表示方法的结果

3、动态代理的实现

1)用户接口类

                    public interface Userdao {
			void add();
			void del();
			void revise();
			void look();
		    }

2)用户接口的实现类

                    public class Userdaoimpl implements Userdao{
			@Override
			public void add() {
				System.out.println("增");
			}
			@Override
			public void del() {
				System.out.println("删");
			}
			@Override
			public void revise() {
				System.out.println("改");
			}
			@Override
			public void look() {
				System.out.println("查");
			}
		    }


3)测试类

                    import java.lang.reflect.Proxy;
    		    public class UserDemo {
			public static void main(String[] args) {
				Userdaoimpl user = new Userdaoimpl();
				Class clazz = user.getClass();
				Object obj = Proxy.newProxyInstance(clazz.getClassLoader(), 
						clazz.getInterfaces(),new MyInvocationHandler(user));
				Userdao newuser = (Userdao) obj;
				newuser.add();
				newuser.del();
				newuser.revise();
				newuser.look();
			}
	            }


4)InvocationHandler的实现类

                    import java.lang.reflect.InvocationHandler;
		    import java.lang.reflect.Method;
		    public class MyInvocationHandler implements InvocationHandler {
			Object obj;
		        public MyInvocationHandler(Object obj) {
				super();
				this.obj = obj;
			}
			@Override
			public Object invoke(Object proxy, Method m, Object[] arg)throws Throwable {
				System.out.println("权限校验");
				Object object = m.invoke(obj, arg);
				System.out.println("记录日志");
				return object;
			}
		    }