Java动态代理的学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ITdevil/article/details/84109220

说动态代理之前,先说一下spring对事物的管理。我们都知道Spring有两大概念,即IOC(控制反转)和AOP(面向切面编程),spring就是利用AOP的原理来实现对事物的管理,而AOP又是使用了动态代理,那具体是怎么做的呢?简单说明一下:

在未使用框架之前,比如使用JDBC阶段,每次使对象入库做save操作的时候,我们都需要手动的去打开连接,提交事物,关闭连接,一万次save操作,就要打开一万次连接,提交一万次事物,关闭一万次连接。我们就想着抽取一些共性来,将相同的操作提取出来做一些优化,相同的操作是什么?打开连接、关闭连接,这两步是一样的,对于执行保存操作的方法肯定每次存取的值不同,不能够抽取。那与动态代理有什么关联呢?动态代理一个作用就是实现对某个方法的增强,而这个方法就是save方法,我们只需要创建一个代理,让代理每次遇到save方法的时候,就将抽取出来的打开连接、关闭连接的操作应用到save方法上,就简单很多,不用自己去手动控制了,”动态“,是指程序在运行时。

文章中用到的名词解释:被代理类和代理类的关系,类似于淘宝商家把货物委托到淘宝平台去销售

被代理类:淘宝的商家

代理类:相当于“淘宝”的角色

处理程序:委托的整个流程

一、正文开始,首先我们需要创建一个统一的接口——人,正常人都需要工作,这是人的共性

package com.sinosoft.test;

public interface Person {
	void work();
}

二、程序员也需要工作,工作内容就比如是将数据入库,他实现了Person的接口

package com.sinosoft.test;

/**
 * 被代理的类
 */
public class ITMan implements Person {

	@Override
	public void work() {
		System.out.println("保存数据入库");
	}

}

三、处理程序Handler类,里面有一个invoke方法,可以在执行保存操作之前自动打开数据库连接,执行完保存操作以后自动关闭数据库连接

package com.sinosoft.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 *请求处理类,相当于代理类要执行“被代理类所实现接口中的方法” 
 *就要先调用这个处理类中的处理程序
 */
public class MyHandler implements InvocationHandler {
	
	public Object obj;//定义“被代理类”的引用
	
	public MyHandler(Object obj){
		this.obj=obj;
	}
	
	/**
	 * 代理类调用了某个方法,就会来调用这个处理程序,就是下面的invoke方法,
	 * 第一个参数基本不用,第二个参数是传过来的方法,第三个参数是传过来方法的参数数组
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		before();
		//反射:相当于执行“被代理类”的method方法--即传过来的work方法
		method.invoke(obj, args);
		after();
		return null;
	}
	
	public void before(){
		System.out.println("打开数据库的连接");
	}
	
	public void after(){
		System.out.println("关闭数据库的连接");
	}
	
	/**
	 *每个代理类都要有一个与之关联的InvocationHandler,因为代理类本身并不处理方法,
	 *而是交给它的handler去处理它的invoke方法 
	 */
}

四、测试类, 目的是创建代理对象,让代理对象去执行被代理对象的方法,实现每次入库前自动打开连接,入库以后自动关闭连接。详细解释都在代码注释里面。

package com.sinosoft.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/***
 * 动态代理:目的是实现方法的增强
 * 创建代理类的步骤:
 * 1、创建”被代理类“的对象
 * 2、调用处理程序类即Handler类的构造,来创建InvocationHandler对象
 * 3、使用java提供的proxy类的newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler)方法来创建代理类对象
 *
 */
public class TestProxy {
	public static void main(String[] args) {
		//创建“被代理类”的对象,需要代理谁,就创建谁
		ITMan man = new ITMan();
		//InvocationHandler是代理对象的“调用处理程序”的入口
		InvocationHandler handler = new MyHandler(man);
		/**
		 * 生成一个代理对象,这个对象即不是ITMan的实例,也不是MyHandler的实例,它是运行期间动态生成的那个实例,这个实例
		 * 实现了被代理类实现的接口--即ITMan.class.getInterfaces(),也就是实现了person接口,所以根据多态转换成了
		 * Person接口类型
		 */
		//参数说明:(定义代理类的类加载器,代理类要实现的接口列表,指派方法调用的调用处理程序)
		Person proxy=(Person)Proxy.newProxyInstance(TestProxy.class.getClassLoader(), ITMan.class.getInterfaces(), handler);
		//让代理类去调用handler的处理程序,即invoke
		proxy.work();
	}
	
	/**
	 * 当我们需要创建一个代理对象的时候,就使用它的newProxyInstance()方法,改方法主要是完成了两件事情,首先是动态的创建了一个类,然后生成该类的实例
	 * 创建完这个类,首先首先得加载到内存里面去,就是用这个类加载器完成的
	 */
}

猜你喜欢

转载自blog.csdn.net/ITdevil/article/details/84109220