java 反射 动态代理AOP

简单介绍下动态代理的基本用法详细的后面补充

AOP(Aspect Orient Program, 面向切面编程)

面向切面编程,可以将一些系统性相关的编程工作(如日志,验证,事务等),独立实现,然后通过切面切入进系统。

非面向切片变成会导致的问题:

代码混乱: 每个方法在处理核心逻辑时还必须兼顾其他多个关注点.

代码分散: 以日志需求为例, 只是为了满足这个单一需求, 就不得不在多个模块里多次重复相同的日志代码. 如果日志需求发生变化, 必须修改所有模块

面向切面的简图

 

例如,要编写个计算器,实现加减的功能,在每次调用方法前后都打印出日志,若在方法体里面写的话,需要修改的话要把所有方法的日志都修改,我们可以通过一个代理对象去代理这个计算器,每次想用计算器的方法时,让代理先打印出来日志,再调用被代理对象(计算器)的方法,再打印出日志.通过代理对象动态地调用被代理对象(计算器)的方法,叫做动态代理

Proxy类 它也是所有动态代理类的父类., java.lang.reflect.Proxy

常用方法

static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)通过静态方法创建一个代理对象,通常情况下,该代理对象是被代理对象实现的接口的类型,或者其他的接口的类型

参数1,类加载器,要跟被代理对象使用的相同的类加载器,参数2,接口类型的Class的数组,如代理对象只需要实现被代理对象实现的接口,  可以写成 target.getClass().getInterfaces(),其中target是被代理对象,参数3 InvocationHandler是个接口,参数3是该接口的实现,常使用匿名内部类的方式

 

InvocationHandler接口   java.lang.reflect,只有一个抽象方法

invoke(Object proxy, Method method, Object[] args)执行被代理对象的方法

参数1,Object类型的proxy,指的是正在被返回的那个代理对象,通常不用这个参数,不然容易出现栈溢出

参数2,代理对象正在调用的方法,参数3代理对象调用方法时传入的参数

下面来示例下:

计算器接口

public interface Calculator {
	public int add(int a,int b);
	public int sub(int a,int b);
}

实现类:

public class MathCalculator implements Calculator {

	@Override
	public int add(int a, int b) {
		int i =a+b;
		return i;
	}

	@Override
	public int sub(int a, int b) {
		int i=a-b;
		return i;
	}	
}

需要实现的功能是在每次调用add或者sub的前后各输出一句话,定义InvocationHandler实现类有点困难,使用匿名内部类

package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class TestCal {
	public static void main(String[] args) {
		//创建被代理对象
		final MathCalculator mc = new MathCalculator();
		//创建代理对象,返回被代理对象接口的类型
		//3个参数,1代理对象的类加载器,2,代理对象要实现的接口的Class数组
		//3new InvocationHandler实例,匿名内部类
		Object proxy = Proxy.newProxyInstance(mc.getClass().getClassLoader(), mc.getClass().getInterfaces(),
				new InvocationHandler() {
			//重写invoke方法,参数1,不用它,参数2,代理对象调用的方法,参数3,方法需要传入的参数
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("hello " + method.getName() + " parameter is: " + Arrays.asList(args));
						Object result = method.invoke(mc, args);// 第一个参数,被代理类的对象.第二个参数,args
						System.out.println("world" + "  the result is " + result);
						return result;
					}
				});
		Calculator cal = (Calculator) proxy;
		cal.add(10, 20);
		cal.sub(10, 60);

	}
}
out:
hello add parameter is: [10, 20]
30
world  the result is 30
hello sub parameter is: [10, 60]
-50
world  the result is -50

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值