反射、通过Class获取Constructor--构造方法、通过Class获取Method --成员方法、通过Class获取Field成员变量、反射读取配置文件、反射技术实现JDK动态代理

文章目录

    • 反射
      • 反射的基本使用
          • 通过Class获取Constructor 构造方法
            • 代码实现过程
          • 通过Class获取Method 成员方法
            • 代码实现过程
          • 通过Class获取Field 成员变量
            • 代码实现过程
      • 反射应用
        • 如何将反射应用在配置文件中
        • 如何读取src目录下的properties配置文件
        • 如何给ArrayList 加入Integer类型
      • 通过反射技术实现动态代理(JDK动态代理)

反射

什么是反射?
    反射就是通过获取类的字节码文件对象:Class
    创建该类的实例(通过构造方法:Constroctor类),调用成员方法(Method类),
    给成员变量赋值(Field类)
 反射的应用
 	ArrayList 如何存储Integer类型
 将某个类的全限定名称作为一个配置文件去使用
 	className = com.test.test1
 	
 jdk动态代理--反射实现的- InvocationHandler代理处理程序

反射的基本使用

通过Class获取Constructor 构造方法
public Constructor[] getConstructors()
	获取当前类中所有的公共的构造方法
public Constructor[] getDeclaredConstructors()
	获取当前类中所有的构造方法: 公共的 私有的 默认的 受保护的
public Constructor getConstructor(Class... parameterTypes)
	获取指定的公共的构造方法
	参数parameterTypes 可变参数 里面相当于数组
	参数是当前的字节码文件Class
public Constructor getDeclaredConstructor(Class... parameterTypes)
	获取指定的构造方法
	参数parameterTypes 可变参数 里面相当于数组
    参数是当前的字节码文件Class
public void setAccessible(boolean flag):参数为true,取消java语言访问检查
public T newInstance() 直接创建该类实例
代码实现过程
package com.reflect_01;
import java.lang.reflect.Constructor;
public class ReflectDemo {
     
	public static void main(String[] args) throws Exception {
     
		Class c = Class.forName("com.reflect_01.Person");
		//获取指定的构造方法
		Constructor con = c.getDeclaredConstructor(
          				  String.class,int.class,String.class);
		//取消java语言访问检查
		con.setAccessible(true);
        //创建该类实例
		Object obj = con.newInstance("弟弟",20,"地球");
		System.out.println(obj);//Person [name=弟弟, age=20, address=地球]
	}
}
通过Class获取Method 成员方法
public Method getDeclaredMethod(String name, Class... parameterTypes)
	获取指定的方法
public Method getMethod(String name,Class... parameterTypes)
    获取公共的成员方法
    参数1: 方法名
    参数2: 当前如果该方法有形式参数
public Method[] getDeclaredMethods()
	获取所有的方法:仅限本类中的,不包括继承的
public Method[] getMethods()
	获取所有的公共的成员方法: 不仅有本类的还有继承的
	
对指定成员方法进行调用,
public Object invoke(Object obj, Object... args)
		参数1: 当前类的实例
		参数2: 类的形式参数
public T newInstance() 直接创建该类实例		
代码实现过程
package com.reflect_02;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@SuppressWarnings("all")
public class ReflectDemo3 {
     
	public static void main(String[] args) throws Exception {
     
		Class c = Class.forName("com.reflect_01.Person");
		//获取构造器--无参构造方法
		Constructor con = c.getConstructor();
		//创建该类的实例
		Object obj = con.newInstance();	
/*		
		public void show() {
			System.out.println("show person");
		}
*/	
		Method m = c.getMethod("show");
		m.invoke(obj); //相当于使用对象名.show()
		//show person
		System.out.println("---------------");
/*		
		public String method(int num) {
			return "helloJavaEE"+num ;
		}
*/		
		Method m2 = c.getMethod("method", int.class);
        //调用 method(int num)
		Object object = m2.invoke(obj, 100);
		System.out.println(object);// helloJavaEE100
		System.out.println("---------------");
/*			
		private  void function(String str) {
			System.out.println(str);
		}
*/
		Method m3 = c.getDeclaredMethod("function", String.class);
		m3.setAccessible(true);
        //调用 function(String str)
		m3.invoke(obj, "hello,world");//hello,world
		
		
	}
}
通过Class获取Field 成员变量
public Field[] getDeclaredFields()获取所有的字段
public Field[] getFields()获取所有的公共的字段
public void setAccessible(boolean flag):参数为true,取消java语言访问检查
赋值: 如果获取所有的字段,赋值之前需要取消java语言访问检查
public void set(Object obj, Object value)
    参数1: 当前Person类的实例
    参数2: 给当前成员字段"name"设置的内容
public T newInstance() 直接创建该类实例
代码实现过程
package com.reflect_02;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@SuppressWarnings("all")
public class ReflectDemo2 {
     
	public static void main(String[] args) throws Exception {
     
		Class c = Class.forName("com.reflect_01.Person");
		//获取构造器
		Constructor con = c.getConstructor();
		//创建该类实例
		Object obj = con.newInstance();
		
/*
		Field[] fields = c.getDeclaredFields();
		获取所有的字段
		for (Field f : fields) {
			System.out.println(f);
		}
		打印结果:
		private java.lang.String com.reflect_01.Person.name
		int com.reflect_01.Person.age
		public java.lang.String com.reflect_01.Person.address
*/    
/*        
		Field[] fields = c.getFields();
		获取所有的公共的字段
		for (Field f : fields) {
			System.out.println(f);
		}
		打印结果:
		public java.lang.String com.reflect_01.Person.address
*/        
		//给 name 赋值
		Field fields = c.getDeclaredField("name");
		//取消java的语言访问检查
		fields.setAccessible(true);
		fields.set(obj, "弟弟");
		System.out.println(obj);//Person [name=弟弟, age=0, address=西安]
		System.out.println("----------");
		//给address赋值
		Field fields2 = c.getDeclaredField("address");
		fields2.setAccessible(true);
		fields2.set(obj, "西安");
		System.out.println(obj);//Person [name=弟弟, age=0, address=西安]
		System.out.println("-------------");	
	}
}

反射应用

如何将反射应用在配置文件中

package com.qianfeng.reflect_03;
import java.io.FileReader;
import java.io.Reader;
import java.lang.reflect.Method;
import java.util.Properties;
/**
 * 
 * 利用Class.forName("类的全限定名") ;将类的全限定名放置在配置文件中
 * xx.txt 文本文件
 * xx.properties文件
 *
 */
@SuppressWarnings("all")
public class Test {
     
	public static void main(String[] args) throws  Exception {
     
		//使用反射
		//创建属性集合类对象
		Properties prop = new Properties() ;		
		//将文本文件中加载到属性集合类中
		Reader r = new FileReader("class.txt") ;
        /*   class.txt
                    className=com.reflect_03.worker
                    methodName=love
        */
		prop.load(r);
		r.close();
		System.out.println(prop);
		//getProperty(String key)---获取值
		String className = prop.getProperty("className") ; //当前类的全限定名
		String methodName = prop.getProperty("methondName") ;//获取方法名
		//反射获取当前类Class对象
		Class  c = Class.forName(className) ;
		//Class类中---public T newInstance():直接创建
		Object obj = c.newInstance() ;
		//获取成员Method
		Method m = c.getMethod("love") ;
	  	//调用love 方法
		m.invoke(obj) ;
	}
}

package com.reflect_03;
public class Student {
     
	public void love() {
     
		System.out.println("Student love...");
	}
}

package com.reflect_03;
public class worker {
     
	public void love() {
     
		System.out.println("Worker love...");
	}
}

如何读取src目录下的properties配置文件

package com.qianfeng.reflect_03;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
/*
 * 如何读取src目录下的properties配置文件
 */
public class Test2 {
     
	
	public static void main(String[] args) throws Exception {
     
		
		//读取src目录下class.properties配置文件
		//封装当前类加载器
		ClassLoader classLoader = Test2.class.getClassLoader();
		//方式1:
		//public InputStream getResourceAsStream(String name)
		//读取指定资源的输入流   
		//参数是文件名称  文件必须是在src目录下(类路径)
		InputStream inputStream = classLoader.getResourceAsStream(
											"class.properties");
		/*	class.properties:
                className=com.reflect_03.worker
                methodName=love
		*/
		
		//方式2:通过类加载器获取网络资源地址对象:URL
		//public URL getResource(String name)
		//public String getPath()
		//创建属性集合类对象
		Properties prop = new Properties() ;
		//将流中的数据加载到属性集合类中
		prop.load(inputStream);

		//通过键的名称获取值
		String className = prop.getProperty("className") ;
		String methodName = prop.getProperty("methondName") ;
		
		//获取当前类的Class
		Class c	 = Class.forName(className) ;
		//直接获取该类实例
		Object obj = c.newInstance() ;
		//获取Method成员方法
		Method m = c.getMethod(methodName) ;
		m.invoke(obj) ;
	}
}

如何给ArrayList 加入Integer类型

package com.reflect_03;

import java.lang.reflect.Method;
import java.util.ArrayList;
@SuppressWarnings("all")
/*
 	ArrayList集合,给里面添加String类型的数据  通过反射
 */
public class Test3 {
     
	public static void main(String[] args) throws Exception {
     
		ArrayList<Integer> array = new ArrayList<Integer>();
		array.add(10);
		array.add(20);
		//直接获取arrayList集合的字节码文件对象
		Class c = array.getClass();
		System.out.println(c);//class java.util.ArrayList
        //获取当前Method类对象:成员方法
		Method m = c.getMethod("add", Object.class);
        //调用add方法
		m.invoke(array, "hello");
		System.out.println(array);
	}
}

通过反射技术实现动态代理(JDK动态代理)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/*
  设计模式:
  	结构型设计模式:
  		代理模式
  			静态代理
  			动态代理
  				jdk动态代理
  				CGlib动态代理
  
  
  静态代理:--------Thread 的实现方式2  implements Runnable接口
  		真实角色:专注于自己的功能
  		代理角色:帮助真实角色对实际的方法进行增强
  			都需要实现指定的接口'
  
  动态代理:在程序的运行过程中产生的代理类
  		JDK动态代理
  		Proxy 提供用于创建动态代理类和实例的静态方法
  
  静态方法:
  	public static Object newProxyInstance
		(
			ClassLoader loader,
		    Class[] interfaces,
            InvocationHandler h
         )
         
     参数1:表示类的加载器
     参数2:获取类的接口列表的Class字节码文件
     参数3:代理实例的处理程序		接口:InvocationHandler
     		
     		JDK动态代理:在程序运行过程中,通过反射的产生的代理类(Proxy以及它里面
     		代理的处理程序:InvocationHandler)

 */
public class Test {
     	
	public static void main(String[] args) {
     		
		//创建接口类对象
		//接口多态
		UserDao ud = new UserDaoImpl() ;
		//MyInvocationHandler实现接口:InvocationHandler:处理程序
		InvocationHandler my = new MyInvocationHandler(ud) ;//对ud
		//对ud产生一个代理类
		//UserDao(真实角色)----UserDaoImpl
		UserDao ud3 = (UserDao) Proxy.newProxyInstance(ud.getClass().getClassLoader(), 
				ud.getClass().getInterfaces(), my) ;
		ud3.add();// 权限校验--代理   增   产生日志记录文件--代理
		ud3.delete();//权限校验--代理  删   产生日志记录文件--代理
		ud3.search();//权限校验--代理  查    产生日志记录文件--代理
		ud3.update();//权限校验--代理   改    产生日志记录文件--代理
	}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//代理类指派的处理程序
public class MyInvocationHandler implements InvocationHandler {
     
	//声明实例 对谁产生代理
	private Object target;//目标类型
	public MyInvocationHandler(Object target) {
     
		this.target = target;
	}
	//参数1 代理实例
	//参数2:实际调用的方法
	//参数3:实际参数
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) 
									throws Throwable {
     
		System.out.println("权限校验--代理");
		Object obj = method.invoke(target, args);
		System.out.println("产生日志记录文件--代理");
		return obj;//返回代理类实例
	}

}
//增删查改接口
public interface UserDao {
     
	void add();
	void delete();
	void search();
	void update();
}
//增删查改子实现类
public class UserDaoImpl implements UserDao {
     
	@Override
	public void add() {
     
		System.out.println("增");
	}
	@Override
	public void delete() {
     
		System.out.println("删");
	}
	@Override
	public void search() {
     
		System.out.println("查");
	}
	@Override
	public void update() {
     
		System.out.println("改");
	}
}

你可能感兴趣的:(java,反射,class,proxy)