• 反射和动态代理


    一、java中的反射

    1.通过反射加载类的属性和方法实例代码:

    /**
    		 *  java.lang.Class 是反射的源头
    		 *  我们创建了一个类,通过编译(javac.exe)生成对应的class文件,之后我们通过java.exe加载(jvm的类加载器加载)此class文件
    		 *  此class文件加载到内存后,就是一个运行时类,存在缓存区,这个运行时类本事就是一个Class的实例
    		 *  每一个运行时类只加载一次,
    		 */
    		Class<StudentExam> clazz = StudentExam.class;
    		StudentExam studentExam = clazz.newInstance();
    		System.err.println(studentExam);
    		
    		System.out.println(clazz);
    		// Field field = clazz.getField("id"); // 通过属性调用运行时类的指定属性:属性是public类型
    		Field field = clazz.getDeclaredField("id"); // 属性是非public 类型
    		Field[] fields = clazz.getDeclaredFields(); // 获取运行时类本身(父类不行)所有声明的属性,父类使用clazz.getFields();
    		for (Field field2 : fields) {
    			int i = field2.getModifiers();
    			String type = Modifier.toString(i);// 获取字段属性的数据类型
    			System.out.println(type);
    		}
    		field.setAccessible(true);
    		field.set(studentExam, 11);
    		System.err.println(studentExam.getId());
    		
    		// 通过反射调用运行时类的指定方法
    		Method method = clazz.getMethod("setId", Integer.class);
    		method.invoke(studentExam, 123); // 调用运行时类的指定方法
    		Method[] methods = clazz.getMethods(); // 获取所有运行时类及其父类中所有声明为public的方法
    		Method[] methods2 = clazz.getDeclaredMethods();// 获取运行时类本身类中声明的方法
    		for (Method method2 : methods) {
    			System.out.println(method2.getName());
    		}
    		
    		// * 通过对象的getClass()方法获取对象的运行时类,
    		Exam exam = new Exam();
    		Class clazzExam = exam.getClass();
    

    2.类加载器ClassLoader

    /**
    	 * Description:类加载器,加载xx.properties文件,并读取数据
    	 * @param 
    	 * @author xiazhongwei
    	 * @data 2016年9月29日:下午5:32:56
    	 * @return
    	 */
    	public void classLoader() throws IOException {
    		//方法一、从当前工程下加载
    		ClassLoader loader = this.getClass().getClassLoader();
    		// 路径是包下写:com\able\onlineExam\resources\config.properties
    		InputStream inStream = loader.getResourceAsStream("config.properties");
    		// 方法二、从指定的路径下加载文件
    		// FileInputStream fileInputStream = new FileInputStream(new File("config.properties"));
    		
    		Properties properties = new Properties();
    		properties.load(inStream);
    		// properties.load(fileInputStream);
    		String prop = properties.getProperty("domain");
    		System.out.println(prop);
    	}
    

    3.动态代理

    静态代理:代理类和目标对象的类型都是在编译期间确定下来,不利于程序的扩展。同时每个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。

    动态代理:客户通过代理类来调用其他对象的方法,并且是在程序运行时,根据需要动态创建目标类的代理对象。

    代理设计模式的原理:

    使用一个代理将对象包装起来,然后用该代理对象取代原始对象,任何对原始对象的调用都要通过代理,代理对象决定的那个是否以及何时将方法调用

    package com.test.junit;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
    
    	public static void main(String[] args) {
    		RealSubject realSubject = new RealSubject();
    		MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
    		Object object = myInvocationHandler.bind(realSubject);
    		Subject subject = (Subject) object;
    		subject.action();
    	}
    }
    // 动态代理的使用
    interface Subject{
    	void action();
    }
    // 被代理类
    class RealSubject implements Subject{
    
    	@Override
    	public void action() {
    
    		System.out.println("我是被代理类,记得执行我哦。。。。");
    	}
    	
    }
    
    class MyInvocationHandler implements InvocationHandler{
    
    	Object object;// 实现了接口的被代理类的对象的声明
    	/**
    	 * Description:①给被代理的对象实例化 ②返回一个代理类对象
    	 * @param 
    	 * @author xiazhongwei
    	 * @data 2016年9月29日:下午4:13:43
    	 * @return
    	 */
    	public Object bind(Object object){
    		this.object = object;
    		return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    	}
    	/**
    	 * 当通过代理类的对象发起对被重写的方法的调用时,都会转化为对如下的invok方法的调用
    	 */
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args)
    			throws Throwable {
    		Object returnObject = method.invoke(object, args);
    		return returnObject;
    	}
    }
    

    4.动态代理与AOP

     示例一、

    package com.atguigu.spring.aop;
    
    public interface ArithmeticCalculator {
    	int add(int i, int j);
    	int sub(int i, int j);
    	
    	int mul(int i, int j);
    	int div(int i, int j);
    }
    

      

    package com.atguigu.spring.aop;
    
    import org.springframework.stereotype.Component;
    
    @Component("arithmeticCalculator")
    public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    
    	@Override
    	public int add(int i, int j) {
    		int result = i + j;
    		return result;
    	}
    
    	@Override
    	public int sub(int i, int j) {
    		int result = i - j;
    		return result;
    	}
    
    	@Override
    	public int mul(int i, int j) {
    		int result = i * j;
    		return result;
    	}
    
    	@Override
    	public int div(int i, int j) {
    		int result = i / j;
    		return result;
    	}
    
    }
    

      

    package com.atguigu.spring.aop;
    
    public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator {
    
    	@Override
    	public int add(int i, int j) {
    		System.out.println("The method add begins with [" + i + "," + j + "]");
    		int result = i + j;
    		System.out.println("The method add ends with " + result);
    		return result;
    	}
    
    	@Override
    	public int sub(int i, int j) {
    		System.out.println("The method sub begins with [" + i + "," + j + "]");
    		int result = i - j;
    		System.out.println("The method sub ends with " + result);
    		return result;
    	}
    
    	@Override
    	public int mul(int i, int j) {
    		System.out.println("The method mul begins with [" + i + "," + j + "]");
    		int result = i * j;
    		System.out.println("The method mul ends with " + result);
    		return result;
    	}
    
    	@Override
    	public int div(int i, int j) {
    		System.out.println("The method div begins with [" + i + "," + j + "]");
    		int result = i / j;
    		System.out.println("The method div ends with " + result);
    		return result;
    	}
    
    }
    

      

    package com.atguigu.spring.aop;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    
    public class ArithmeticCalculatorLoggingProxy {
    	
    	//要代理的对象
    	private ArithmeticCalculator target;
    	
    	public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {
    		super();
    		this.target = target;
    	}
    
    	//返回代理对象
    	public ArithmeticCalculator getLoggingProxy(){
    		ArithmeticCalculator proxy = null;
    		// 代理对象有哪一个类加载器负责加载
    		ClassLoader loader = target.getClass().getClassLoader();
    		// 代理对象的类型,即其中有哪些方法
    		Class [] interfaces = new Class[]{ArithmeticCalculator.class};
    		// 当调用代理对象的其中方法时,执行下面的代码
    		InvocationHandler h = new InvocationHandler() {
    			/**
    			 * proxy: 代理对象。 一般不使用该对象
    			 * method: 正在被调用的方法
    			 * args: 调用方法传入的参数
    			 */
    			@Override
    			public Object invoke(Object proxy, Method method, Object[] args)
    					throws Throwable {
    				// 在方法内部不会直接调用proxy对象的某个方法,proxy.toString()会造成死循环调用invoke方法
    				String methodName = method.getName();
    				//打印日志
    				System.out.println("[before] The method " + methodName + " begins with " + Arrays.asList(args));
    				
    				//调用目标方法
    				Object result = null;
    				
    				try {
    					//前置通知
    					result = method.invoke(target, args);
    					//返回通知, 可以访问到方法的返回值
    				} catch (NullPointerException e) {
    					e.printStackTrace();
    					//异常通知, 可以访问到方法出现的异常
    				}
    				
    				//后置通知. 因为方法可以能会出异常, 所以访问不到方法的返回值
    				
    				//打印日志
    				System.out.println("[after] The method ends with " + result);
    				
    				return result;
    			}
    		};
    		
    		/**
    		 * loader: 代理对象使用的类加载器。 
    		 * interfaces: 指定代理对象的类型. 即代理代理对象中可以有哪些方法. 
    		 * h: 当具体调用代理对象的方法时, 应该如何进行响应, 实际上就是调用 InvocationHandler 的 invoke 方法
    		 */
    		proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
    		
    		return proxy;
    	}
    }
    

      

    package com.atguigu.spring.aop;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
    	
    	public static void main(String[] args) {
    		// ArithmeticCalculator arithmeticCalculator = new ArithmeticCalculatorImpl();
    		ArithmeticCalculator arithmeticCalculator = new ArithmeticCalculatorLoggingImpl();
    		
    		arithmeticCalculator = new ArithmeticCalculatorLoggingProxy(arithmeticCalculator).getLoggingProxy();
    		
    		int result = arithmeticCalculator.add(11, 12);
    		System.out.println("result:" + result);
    		
    		result = arithmeticCalculator.div(21, 3);
    		System.out.println("result:" + result);
    		
    	}
    	
    }
    

      示例二、

    package com.test.junit;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
    
    	public static void main(String[] args) {
    		RealSubject realSubject = new RealSubject();
    		MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
    		Object object = myInvocationHandler.bind(realSubject);
    		Subject subject = (Subject) object;
    		subject.action();
    	}
    }
    // 动态代理的使用
    interface Subject{
    	void action();
    }
    // 被代理类
    class RealSubject implements Subject{
    
    	@Override
    	public void action() {
    
    		System.out.println("我是被代理类,记得执行我哦。。。。");
    	}
    	
    }
    
    class MyInvocationHandler implements InvocationHandler{
    
    	Object object;// 实现了接口的被代理类的对象的声明
    	/**
    	 * Description:①给被代理的对象实例化 ②返回一个代理类对象
    	 * @param 
    	 * @author xiazhongwei
    	 * @data 2016年9月29日:下午4:13:43
    	 * @return
    	 */
    	public Object bind(Object object){
    		this.object = object;
    		return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    	}
    	/**
    	 * 当通过代理类的对象发起对被重写的方法的调用时,都会转化为对如下的invok方法的调用
    	 */
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args)
    			throws Throwable {
    		Object returnObject = method.invoke(object, args);
    		return returnObject;
    	}
    }
    

      

  • 相关阅读:
    阅读《构建之法》1-5章
    构建之法第8,9,10章
    实验5-封装与测试2
    第六次作业-my Backlog
    保存内容
    实验四-单元测试
    实验3—修改版
    做汉堡-57号
    实验3-2
    201306114357-实验3-C语言
  • 原文地址:https://www.cnblogs.com/ablejava/p/5920893.html
Copyright © 2020-2023  润新知