javaAPI_反射_反射基础2
反射基础知识2以及反射的相关应用
1.通过反射运行配置文件内容
  (1).创建配置文件
    class.txt
	内容[可修改]
	className=cn.itcast.test.Worker
    methodName=love
      
  (2).要使用的对象[仅仅为测试方便]
     
	//学生类
	public class Student {
	public void love() {
		System.out.println("爱生活,爱Java");
	}
    }
	
	//老师类
	public class Teacher {
	public void love() {
		System.out.println("爱生活,爱青霞");
	}
    }
	
	//工人类
	public class Worker {
	public void love() {
		System.out.println("爱生活,爱老婆");
	}
    }
  
  (3).测试类代码
   public static void main(String[] args) throws Exception {
		// 反射前的做法
		// Student s = new Student();
		// s.love();
		// Teacher t = new Teacher();
		// t.love();
		// Worker w = new Worker();
		// w.love();
		// 反射后的做法
		// 加载键值对数据
		Properties prop = new Properties();
		FileReader fr = new FileReader("class.txt");
		prop.load(fr);
		fr.close();
		// 获取数据
		String className = prop.getProperty("className");
		String methodName = prop.getProperty("methodName");
		// 反射
		Class c = Class.forName(className);
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();
		// 调用方法
		Method m = c.getMethod(methodName);
		m.invoke(obj);
	}
2.通过反射,越过泛型检查
 (1).要求:
     我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
 (2).代码实现
   public static void main(String[] args) throws NoSuchMethodException,
			SecurityException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		// 创建集合对象
		ArrayList<Integer> array = new ArrayList<Integer>();
		// array.add("hello");
		// array.add(10);
		Class c = array.getClass(); // 集合ArrayList的class文件对象
		Method m = c.getMethod("add", Object.class);
		m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello
		m.invoke(array, "world");
		m.invoke(array, "java");
		System.out.println(array);
	}
3.通过反射写一个通用的设置某一个对象的某个对象的某一个属性为指定的值。
  (1).使用的工具类
  public void setProperty(Object obj, String propertyName, Object value)
			throws NoSuchFieldException, SecurityException,
			IllegalArgumentException, IllegalAccessException {
		// 根据对象获取字节码文件对象
		Class c = obj.getClass();
		// 获取该对象的propertyName成员变量
		Field field = c.getDeclaredField(propertyName);
		// 取消访问检查
		field.setAccessible(true);
		// 给对象的成员变量赋值为指定的值
		field.set(obj, value);
	}
	
  (2).使用测试 
   public class ToolDemo {
	public static void main(String[] args) throws NoSuchFieldException,
			SecurityException, IllegalArgumentException, IllegalAccessException {
		Person p = new Person();
		Tool t = new Tool();
		t.setProperty(p, "name", "林青霞");
		t.setProperty(p, "age", 27);
		System.out.println(p);
		System.out.println("-----------");
Dog d = new Dog();
		t.setProperty(d, "sex", '男');
		t.setProperty(d, "price", 12.34f);
		System.out.println(d);
	}
    }
   class Dog {
	char sex;
	float price;
	@Override
	public String toString() {
		return sex + "---" + price;
	}
    }
   class Person {
	private String name;
	public int age;
	@Override
	public String toString() {
		return name + "---" + age;
	}
    }
4.动态代理[*****]
  
  (1).概述
      代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
            举例:春季回家买票让人代买
      动态代理:在程序运行过程中产生的这个对象
                而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
  (2).java中的动态代理
  在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理
  对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglibProxy类中的方法创建动态代理类对象
  
  public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
  
  最终会调用InvocationHandler的方法
  
  InvocationHandler
  Object invoke(Object proxy,Method method,Object[] args)
  注意事项:
  Proxy类中创建动态代理对象的方法的三个参数;
  ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
  Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就
  宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
  InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
  每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用
  一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke 方法来进行调用。
  InvocationHandler接口中invoke方法的三个参数:
  proxy:代表动态代理对象
  method:代表正在执行的方法
  args:代表调用目标方法时传入的实参
  Proxy.newProxyInstance
  创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,
  也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,
  以$开头,proxy为中,最后一个数字表示对象的标号。
  System.out.println(u.getClass().getName());
  (3).代码实现
  //一个接口
  public interface UserDao {
	public abstract void add();
public abstract void delete();
public abstract void update();
	public abstract void find();
  }
  
  //一个实现类
  public class UserDaoImpl implements UserDao {
	@Override
	public void add() {
		System.out.println("添加功能");
	}
	@Override
	public void delete() {
		System.out.println("删除功能");
	}
	@Override
	public void update() {
		System.out.println("修改功能");
	}
	@Override
	public void find() {
		System.out.println("查找功能");
	}
    }
	
	//一个接口
	public interface StudentDao {
	public abstract void login();
	public abstract void regist();
    }
	
	//一个实现类
	public class StudentDaoImpl implements StudentDao {
	@Override
	public void login() {
		System.out.println("登录功能");
	}
	@Override
	public void regist() {
		System.out.println("注册功能");
	}
}
	//创建一个动态代理对象类
	public class MyInvocationHandler implements InvocationHandler {
	private Object target; // 目标对象
	public MyInvocationHandler(Object target) {
		this.target = target;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("权限校验");
		Object result = method.invoke(target, args);
		System.out.println("日志记录");
		return result; // 返回的是代理对象
	}
    }
	
	//测试类代码
	public static void main(String[] args) {
		UserDao ud = new UserDaoImpl();
		ud.add();
		ud.delete();
		ud.update();
		ud.find();
		System.out.println("-----------");
		// 我们要创建一个动态代理对象
		// Proxy类中有一个方法可以创建动态代理对象
		// public static Object newProxyInstance(ClassLoader loader,Class<?>[]
		// interfaces,InvocationHandler h)
		// 我准备对ud对象做一个代理对象
		MyInvocationHandler handler = new MyInvocationHandler(ud);
		UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass()
				.getClassLoader(), ud.getClass().getInterfaces(), handler);
		proxy.add();
		proxy.delete();
		proxy.update();
		proxy.find();
		System.out.println("-----------");
		StudentDao sd = new StudentDaoImpl();
		MyInvocationHandler handler2 = new MyInvocationHandler(sd);
		StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass()
				.getClassLoader(), sd.getClass().getInterfaces(), handler2);
		proxy2.login();
		proxy2.regist();
	}
                    
                
                
            
        
浙公网安备 33010602011771号