Spring AOP与动态代理

   AOP就是Spring面向切面编程,经常会在调用某一个方法前或者调用以后去执行其他的操作,这就需要用到AOP原理了
   AOP是怎么做到切面点切入的呢,就是通过动态代理来实现的,动态代理目前主要有JDK的动态代理(InvocationHandler)和Cglib两种
  首先,最早接触到的代理应该是设计模式中的代理模式,是静态代理,主要是有接口类,接口实现类和代理类,代码如下
  ![在这里插入图片描述](https://img-blog.csdnimg.cn/2019102110194620.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xoejEzNTEwOTcwNzQ1,size_16,color_FFFFFF,t_70)

代码如下:
接口类
package test;

public interface Caculate {

public int add(int a,int b);
public int sub(int a,int b);

}

接口实现类
package test;

public class AddCaculate implements Caculate{

@Override
public int add(int a, int b) {
	// TODO Auto-generated method stub
	return a+b;
}

@Override
public int sub(int a, int b) {
	// TODO Auto-generated method stub
	return a-b;
}

}

代理类
package test;

public class CaculateProxy implements Caculate{

private Caculate caculate;

public CaculateProxy(Caculate caculate) {
	
	this.caculate=caculate;
	// TODO Auto-generated constructor stub
}

@Override
public int add(int a, int b) {
	// TODO Auto-generated method stub
	return caculate.add(a, b);
}

@Override
public int sub(int a, int b) {
	// TODO Auto-generated method stub
	return caculate.add(a, b);
}

}

测试
AddCaculate addCaculate = new AddCaculate();
CaculateProxy proxy = new CaculateProxy(addCaculate);
proxy.add(1, 2);
proxy.sub(2, 1);

这里就是静态代理类的实现,那么问题来了,如果需要增添或者删除一些方法,那么代理类也要跟随着做相应的修改,此时就需要动态代理来解决这个问题了,那么动态代理是啥原理实现的呢,看下面一张图
在这里插入图片描述
这是java代码在jvm里边编译解析程子节码的过程,Java的源代码.java文件通过编译器编译成.class文件后,jvm就在加载类的时候,会根据.class的组织结构,生成对应的字节码 再进行加载类,这就实现了.class在运行期间才被确定,就成就了动态代理了
1.InvocationHandler模式
InvocationHandler就是在静态代理模式上引入了InvocationHandler类,这个类就是负责在运行时候,动态调用proxy所要调用的对应实现类的方法,代码如下
接口类和实现类还是和静态代理一样
代理类如下,实现了InvocationHandler:
package test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class CaculateProxy implements InvocationHandler{

private Object caculate;

public CaculateProxy(Object caculate) {
	
	this.caculate=caculate;
	// TODO Auto-generated constructor stub
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	// TODO Auto-generated method stub
	method.invoke(caculate, args);
	return null;
}

}
测试类
AddCaculate addCaculate = new AddCaculate();
InvocationHandler invocationHandler = new CaculateProxy(addCaculate);
Caculate caculate = (Caculate) Proxy.newProxyInstance(addCaculate.getClass().getClassLoader(),
addCaculate.getClass().getInterfaces(), invocationHandler);
caculate.add(2, 3);
caculate.sub(1, 2);
我们看到addCaculate.getClass(),这段代码实际上我们是把实现类中的接口信息与触发器invocationHandler绑定,也就是说如果实现类有接口中没有的方法是不能被代理的。总的来说,JDK这种代理1)要保证有接口,2)不能代理接口中没有的方法
为避免上面的两种缺陷,这就是要说的另一种动态代理实现方式,那就是代理类继承被代理类,不需要接口,这种实现如 Cglib,Cglib是实现了MethodInterceptor拦截器
它的流程是这样的:
1).查找A上的所有非final 的public类型的方法定义;
2).将这些方法的定义转换成字节码;
3).将组成的字节码转换成相应的代理的class对象;
4).实现 MethodInterceptor接口,用来处理 对代理类上所有方法的请求(这个接口和JDK动态代理InvocationHandler的功能和角色是一样的
本文参考文章:http://blog.csdn.net/luanlouis/article/details/24589193

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值