jdk动态代理简单实现springAOP原理

87 阅读4分钟

jdk动态代理简单实现springAOP原理   在近期学习了spring框架,在使用spring官方提供的jar包和配置文件进行了实现,对它内部的实现方法进行了一些了解,并想在此记录并分享出来。这也是我第一次发博客,在排版和内容上会有一些不足,如有错误和建议欢迎大家在下方评论指出!!!

简单介绍一下AOP的相关概念

1、AOP和OOP的关系   AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。 2、相关术语   (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知   (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用   (3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around   (4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式   (5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

个人理解

   相关概念都是度娘上的标准答案。简单来说,就目的而言这个技术就是为了一步减低程序代码间的耦合度,而我们在日常开发中以肯定知到“开闭原则”------对扩展是开放的,对修改是关闭的(这里的修改是指对源码的修改)。AOP可以实现对一个类或一段代码片段不做修改而添加一些给定的功能。

接下来我们便用jdk动态代理来模拟实现一下aop的基础实现过程

这里使用一个例子给大家参考

  当前我们已经完成了一个功能的实现过程

public class Test  {
	public void a(){
		//这里就以一条输出语句作为具体的功能
		System.out.println("功能实现的过程");
	}
}

  后期我们有一个需求:获取功能实现的所需时间,我们的第一反应是在源码的基础上做修改 ` public class JcImpl{ public void a(){ //获取代码执行之前的系统毫秒值 long L1=System.currentTimeMillis();

	System.out.println("功能实现的过程");
	 
	//获取代码执行完之后的系统毫秒值
	long L2=System.currentTimeMillis();
	//将L2减去L1获取运行时间
	long L3=L2-L1;
	System.out.println("代码运行时间为"+L3+"毫秒!!!");
}

} `   这样做虽然能完成对功能的实现,但在软件开发过程中并不推荐这样做,而且对一个已经完成的软件系统源码做修改是一个大忌。接下来我们用动态代理模式对此需求进行实现。

动态代理实现

  这里创建了两个包,一个接口四个类
  1.先定义一个基础类的接口

package com.test.util;
public interface Jc {
	//定义一个接口规范
		void a();
	}

  2.实现类实现接口定义的方法

package com.test.util;
public class JcImpl implements Jc {
	@Override
	public void a() {
		System.out.println("功能实现的过程 ");
	}
}

  3.把获取系统时间的方法单独写到一个类中

package com.test.util;
public class TimeUtil {
	//将系统当前时间的毫秒值返回
	public long getTime() {
		long time=System.currentTimeMillis();
		return time;
	}
}

  4.编写一个代理类,通过构造方法将获取时间的类织入到基础类 ` package com.test.util; //用到的反射的包 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;

//需要实现InvocationHandler接口中的invoke()方法 public class JcImplProxy implements InvocationHandler {

//基础功能对象
private Object obj;
//附加功能对象
private TimeUtil tu;
//定义构造方法将原功能和要附加的功能织入到此工具类中
public JcImplProxy(Object obj,TimeUtil tu) {
	this.obj=obj;
	this.tu=tu;
}

//通过代理实例上的方法调用并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	long L1=tu.getTime();
	Object newObj=method.invoke(obj, args);
	long L2=tu.getTime();
	long L3=L2-L1;
	System.out.println("代码运行时间为"+L3+"毫秒!!!");
	return newObj;
}

`   至此基本功能组件都以编写完成,现在编写一个测试程序

` package com.test.proxytest;

import java.lang.reflect.Proxy; import com.test.util.Jc; import com.test.util.JcImpl; import com.test.util.JcImplProxy; import com.test.util.TimeUtil;

public class ProxyJunit { public static void main(String[] args) { //基础类 Jc obj=new JcImpl(); //附加功能 TimeUtil tu=new TimeUtil(); //通过代理类的构造方法将附加类织入到基础类中 JcImplProxy js=new JcImplProxy(obj, tu); //有三个参数。第一个为基础类的类加载器,第二个为基础类的接口集合,第三个为代理类对象 Jc newjs=(Jc)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),js); newjs.a(); } } `   以下就是运行结果截图,我们并没有对程序的源码进行修改,实现了业务需求。当然我们这里只用了一条输出语句作为具体功能的实现,而现在的cup运行速度是非常快的,所以只用了0毫秒的时间便完成了功能的实现。 运行结果截图

总结

  以上用jdk的动态代理简单的实现了一下aop基础的实现原理。当然我写的很简单,都是基础的东西,如大家有其他看法请在评论区指出。