Java基础之反射及动态代理,反射实现工厂模式

 一,先看一下反射的概念:
              主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
             反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
             看概念很晕的,继续往下看。
 
      二,反射机制的作用:
              1,反编译:.class-->.java
              2,通过反射机制访问java对象的属性,方法,构造方法等;
             这样好像更容易理解一些,下边我们具体看怎么实现这些功能。
 三,在这里先看一下sun为我们提供了那些反射机制中的类:
java.lang.Class;                
java.lang.reflect.Constructor; 
java.lang.reflect.Field;        
java.lang.reflect.Method;
java.lang.reflect.Modifier;

四。从例子看常用的用法:
package reflect;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

public class ReflectTest implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6957472993081091730L;

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException {
		Class class1 = null;
		Class class2 = null;
		Class class3 = null;
		
		class1 = Class.forName("reflect.ReflectTest");//实例化Class类对象-1
		class2 = new ReflectTest().getClass();//实例化Class类对象-2
		class3 = ReflectTest.class;//实例化Class类对象-3
		
		Class parentClass = class1.getSuperclass();//获得父类
		Class intes[] = class1.getInterfaces();//获得所有接口
		
		Class class4 = Class.forName("reflect.User");//完整路径的类名,包括package name
		User user1 = (User) class4.newInstance();// create a user through reflect
		user1.setUsername("lilong");
		Constructor cons[] = class4.getConstructors();
		
		
		ReflectTest reflectTest = new ReflectTest();
		System.out.println("通过一个对象获得完整的包名和类名:" + reflectTest.getClass().getName());
		System.out.println("___________________________");
		
		System.out.println("类名称   " + class1.getName());
        System.out.println("类名称   " + class2.getName());
        System.out.println("类名称   " + class3.getName());
        System.out.println("___________________________");
		
        System.out.println("class1的父类是:"+ parentClass.getName());
        System.out.println("class1实现的接口有:");
        for(int i=0; i clazzs[] = cons[i].getParameterTypes(); //取得各个参数类型构成的Class数组
        	System.out.print("cons[" + i + "] (");
        	for(int j=0; j class5 = Class.forName("reflect.Student");
        System.out.println("===============本类属性===============");
        Field[] fields = class5.getDeclaredFields(); //该类声明的属性
        for(int i=0; i type = fields[i].getType();// 属性类型
        	System.out.println(mo + " " + type.getName() + " " + fields[i].getName() + ";");
        }
        System.out.println("==========实现的接口或者父类的属性==========");
        Field[] fields2 = class5.getFields(); //获得实现的接口或者父类的属性
        for(int i=0; i type = fields2[i].getType();
        	System.out.println(mo + " " + type.getName() + " " + fields2[i].getName() + ";");
        }
        System.out.println("___________________________");
        
        System.out.println("获取某个类的全部方法");
        Class class6 = Class.forName("reflect.Student");
        Method[] method = class6.getMethods();
        for(int i=0; i returnType = method[i].getReturnType();
        	Class[] param = method[i].getParameterTypes();
        	int temp = method[i].getModifiers();
        	System.out.print(Modifier.toString(temp) + " " + returnType.getName() + " " + method[i].getName()+"(");
        	for(int j=0; j[] exce = method[i].getExceptionTypes();
        	if(exce.length > 0){
        		System.out.print(") throws ");
        		for(int k=0; k< exce.length; k++){
        			System.out.print(exce[k].getName() + "");
        			if(k < exce.length -1){
        				System.out.print(",");
        			}
        		}
        	}else {
				System.out.print(")\n");
			}
        	System.out.println();
        }
        System.out.println("___________________________");
        
        System.out.println("通过反射机制调用某个类的方法");
        Class class7 = Class.forName("reflect.Student");
        Method method2 = class7.getMethod("print"); //调用无参方法
        Method method3 = class7.getMethod("print2", String.class);//调用有参方法
     
        try {
			method2.invoke(class7.newInstance());
			method3.invoke(class7.newInstance(), "i am a student too.");
		} catch (IllegalArgumentException | InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        System.out.println("___________________________");
        
        System.out.println("通过反射机制操作某个类的属性");
        Class class8 = Class.forName("reflect.Student");
        Object object = class8.newInstance();
        Field field;
		try {
			field = class8.getDeclaredField("password");
			field.setAccessible(true);
			field.set(object, "lilong123");
			System.out.println("password is " + field.get(object));
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("___________________________");
		
		System.out.println("反射机制的动态代理");
		MyInvocationHandler demo = new MyInvocationHandler();
		Subject sub = (Subject) demo.bind(new RealSubjec());// 接口变量指向?
		String info = sub.say("roolback", 20);
		System.out.println(info);
		System.out.println("___________________________");
        
	}
	
	
	
}

class User implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private String username;

	public User() {
		this.username = "lilong";
	}

	public User(String username) {
		this.username = username;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}
	
}

class Student extends User {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String password;

	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Student(String password) {
		super();
		this.password = password;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	public void print(){
		System.out.println("i am a student.");
	}
	
	public void print2(String str) {
		System.out.println(str);
	}
}

interface Subject{
	public String say(String name, int age);
}

class RealSubjec implements Subject{

	@Override
	public String say(String name, int age) {
		return name + " " + age;
	}
	
}

class MyInvocationHandler implements InvocationHandler{
	
	private Object obj = null;
	/**
	 * 在java中有三种类类加载器。
	 * 
	 * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
	 * 
	 * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
	 * 
	 * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
	 * 
	 * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
	 * 动态代理的代理类是实现了一个InvocationHandler的接口,我们通过reflect.Proxy的类的newProxyInstance方法就可以得到这个接口
的实例,然后再来作为参数传递进去,这里每一个在代理类上处理的东西也会被重定向到调用处理器上。
	 * @author
	 * 
	 */
	public Object bind(Object obj){
		this.obj = obj;
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object temp = method.invoke(this.obj, args);
		return temp;
	}
}










用反射实现工厂模式:
package reflect;

public class ReflectTest2 {

	public static void main(String[] args) {
		Fruit fruit1 = Factory.getInstance("reflect.Apple");
		Fruit fruit2 = Factory.getInstance("reflect.Orange");
		fruit1.eat();
		fruit2.eat();

	}

}

interface Fruit{
	public void eat();
}

class Apple implements Fruit{

	@Override
	public void eat() {
		System.out.println("Apple");
	}
	
}

class Orange implements Fruit{

	@Override
	public void eat() {
		System.out.println("Orange");
	}
	
}

/**
 * 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。
 * Java 工厂模式可以参考
 * http://baike.xsoftlab.net/view/java-factory-pattern
 * 
 * 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
 * 
 * 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。
 * 
 * java 读取 properties 配置文件 的方法可以参考
 * http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file
 * 
 * @author xsoftlab.net
 */
class Factory{
	public static Fruit getInstance(String ClassName) {
		Fruit fruit = null;
		try {
			fruit = (reflect.Fruit) Class.forName(ClassName).newInstance();
		} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
			e.printStackTrace();
		}
		return fruit;
	}
}




你可能感兴趣的:(java基础)