黑马程序员——代理

------- android培训java培训、期待与您交流! ----------

 

代理类

代理类就是将需要代理的目标类中的方法在代理类中调用并添加了新的功能代码

 

功能代码可以添加到下面四个位置

1.      调用的方法之前

2.      调用的方法之后

3.      调用的方法前后

4.      调用的方法异常处理的catch语句中

 

代码示例

package cn.itcast.proxy;

public class ProxyTest {
	public static void main(String[] args) {
		// 调用代理类
		new MyProxy().sayHello();
	}
}

// 需要被代理的目标类
class Target {
	public void sayHello() {
		System.out.println("Hello World");
	}
}

// 代理类
class MyProxy {
	public void sayHello() {
		// 在目标类方法调用前加上功能代码
		System.out.println("before......");
		// 调用目标类的方法
		new Target().sayHello();
		// 在目标类方法调用后加上功能代码
		System.out.println("after......");
	}
}


 

动态代理 AOP

AOP(Aspect oriented program)面向方面编程

系统中存在交叉业务, 一个交叉业务就是要切入到系统的一个方面, 比如安全,事物, 日志,交叉业务的的编程就是AOP, 将交叉业务模块化,将切面代码添加到原始代码的周围, 与在原始代码添加切面代码是一样的(切面是安全,事物, 日志代码)

 

JVM可以动态的生成类的字节码,这些动态生成的类一般被用作代理类, 这些类叫动态代理类

 

动态代理类必须实现一个或多个接口,所以动态代理类只能作用于相同接口的实现类的目标类

 

CGLIB库可以生成一个类的子类,这个子类可以用作这个类的代理类, 所以要为一个没有接口的类生成动态代理类,可以用CGLIB

 

代码示例

package cn.itcast.proxy;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;

public class ProxyTest2 {
	public static void main(String[] args) {
		// 生成一个动态代理的类
		Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(),
				Collection.class);
		System.out.println(clazz);

		System.out.println("------Constuctor-------");
		// 获得代理类的构造方法
		Constructor[] cons = clazz.getConstructors();

		// 循环打印构造方法名包括参数
		for (Constructor constructor : cons) {
			// 得到构造方法名字
			String name = constructor.getName();
			// 获得参数类型
			Class[] clazzParams = constructor.getParameterTypes();
			// 创建StringBuilder对象用于追加方法的参数
			StringBuilder sb = new StringBuilder(name);
			sb.append('(');
			for (Class clazzParam : clazzParams) {
				sb.append(clazzParam.getName()).append(',');
			}
			if (clazzParams == null && clazzParams.length != 0)
				sb.deleteCharAt(sb.length() - 1);
			sb.append(')');
			System.out.println(sb.toString());
		}

		System.out.println("------Method-------");
		// 得到所有方法
		Method[] methods = clazz.getMethods();
		// 循环打印方法名包括参数
		for (Method method : methods) {
			// 得到构造方法名字
			String name = method.getName();
			// 获得参数类型
			Class[] clazzParams = method.getParameterTypes();
			// 创建StringBuilder对象用于追加方法的参数
			StringBuilder sb = new StringBuilder(name);
			sb.append('(');
			for (Class clazzParam : clazzParams) {
				sb.append(clazzParam.getName()).append(',');
			}
			if (clazzParams.length != 0)
				sb.deleteCharAt(sb.length() - 1);
			sb.append(')');
			System.out.println(sb.toString());
		}
	}
}


 

动态代理得到代理类的实例

代码示例

package cn.itcast.proxy;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;

public class ProxyTest3 {
	public static void main(String[] args) throws Exception {
		// 得到Collection接口的动态代理类
		Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(),
				Collection.class);
		// 得到代理类的构造方法
		Constructor constructor = clazz.getConstructor(InvocationHandler.class);
		// 创建代理类的实例
		Collection coll = (Collection) constructor
				.newInstance(new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						// TODO Auto-generated method stub
						return null;
					}
				});
		// 打印得到的代理类
		System.out.println(coll.toString());
		coll.clear();
	}
}


 

InvocationHandler接口

创建代理类实例的时候需要传入一个InvocationHandler对象, InvocationHandler是一个接口,里面有一个抽象方法invoke(Object proxy, Method method, Object[] args),这三个参数分别表示调用的代理类, 调用的方法(根据调用的时候的方法名字判断),传入方法的参数, 一个类的代理类中的方法其实就是调用了这个方法

 

Proxy中有一个直接获得代理类实例的方法

 

代码示例

import java.util.Collection;

public class ProxyTest4 {
	public static void main(String[] args) {
		// final Collection target = new ArrayList();
		// final Advice advice = new Advice();
		// 创建Collection的代理类, 并出入目标对象和系统功能对象
		Collection proxy = (Collection) getProxy(new ArrayList(), new Advice());
		proxy.add("232");
		proxy.add("dff");
		proxy.add(123);

		System.out.println(proxy);
		System.out.println(proxy.size());

	}

	// 获得代理类, 接收一个目标对象和系统功能类
	public static Object getProxy(final Object target, final Advice advice) {
		// 获得Collection的代理类的实例
		Object obj = Proxy.newProxyInstance(target.getClass().getClassLoader(),
		// 可能有多个接口
				target.getClass().getInterfaces(),
				// 匿名内部类重写了invoke方法
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						// 在方法前加入系统功能代码
						advice.before(method);
						Object result = method.invoke(target, args);
						// 在方法后加入系统功能代码
						advice.after(method);
						return result;
					}
				});
		return obj;
	}

}

// 声明一个类, 里面包含系统功能方法(一般会先写一个接口, 然后实现, 这里为了方便直接写了类)
class Advice {

	long start;

	public void before(Method method) {
		start = System.currentTimeMillis();
	}

	public void after(Method method) {
		long end = System.currentTimeMillis();
		System.out.println("调用" + method.getName() + "一共花费了" + (end - start)
				+ "毫秒");
	}
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值