spring AOP的两种代理
本篇记录下spring AOP的两种代理,为下一篇AOP实现做下铺垫。
1.JDK动态代理 2.cglib代理
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
注:JDK动态代理要比cglib代理执行速度快,但性能不如cglib好。所以在选择用哪种代理还是要看具体情况,一般单例模式用cglib比较好,具体原因请自行百度。
一。JDK动态代理实现(原理是使用反射机制)
首先定义接口,并实现
public interface TestService{
public int add();
}
public class TestServiceImpl implements TestService{
@Override
public int add() {
System.out.println("开始执行add...");
return 0;
}
}
定义代理类,这里要注意导入的包是import java.lang.reflect.*
public class JDKDynamicProxy implements InvocationHandler {
//被代理的目标对象
private Object proxyObj;
/**
* Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
* loader :类加载器 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
* interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
* h :一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
*/
public Object newProxy(Object proxyObj){
this.proxyObj = proxyObj;
//返回一个代理对象
return Proxy.newProxyInstance(proxyObj.getClass().getClassLoader(),
proxyObj.getClass().getInterfaces(),
this);
}
/**
* 执行目标对象
* Object proxy:被代理的对象
* Method method:要调用的方法
* Object args[]:方法调用时所需要的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
before();
Object object = method.invoke(this.proxyObj,args); // 通过反射机制调用目标对象的方法
after();
return object;
}
public void before(){
System.out.println("开始执行目标对象之前...");
}
public void after(){
System.out.println("开始执行目标对象之后...");
}
}
测试类:
public static void main(String[] args) {
//我们要代理的真实对象
TestService testService = new TestServiceImpl();
//testJDKProxyService.add();//不是用代理
JDKDynamicProxy JDKDynamicProxyTarget = new JDKDynamicProxy();
TestService testServiceProxy = (TestService) JDKDynamicProxyTarget.newProxy(testService);
//执行代理类的方法
testServiceProxy.add();
}
控制台显示

二。CGLIB代理,需要导入 cglib-nodep-2.1_3.jar
先说下cglib,CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
先定义一个实现类(注意并没有实现接口)
public class TestCGLIBServiceImpl {
public int add() {
System.out.println("开始执行add...");
return 0;
}
}
定义cglib代理类,此时导入的包应该是import net.sf.cglib.proxy.*
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLIBProxy implements MethodInterceptor{
private Object targetObject ;//被代理的目标对象
public Object createProxyInstance(Object targetObject) {
this . targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetObject.getClass());// 设置代理目标
enhancer.setCallback( this );// 设置回调
return enhancer.create();
}
/**
* 在代理实例上处理方法调用并返回结果
* @param object : 代理类
* @param method :被代理的方法
* @param args :该方法的参数数组
* @param methodProxy
*/
@Override
public Object intercept(Object object, Method method, Object[] args,
MethodProxy methodproxy) throws Throwable {
Object result = null;
try {
System. out .println( "前置处理开始 ..." );
result = methodproxy.invoke( targetObject , args);//执行目标对象的方法
System. out .println( "后置处理开始 ..." );
} catch (Exception e) {
System. out .println( " 异常处理 ..." );
} finally {
System. out .println( " 调用结束 ..." );
}
return result;
}
}
测试类:
public class TestCGLIBProxy {
public static void main(String[] args) {
//我们要代理的真实对象
TestCGLIBServiceImpl testCGLIB = new TestCGLIBServiceImpl();
CGLIBProxy CGLIBproxy = new CGLIBProxy();
TestCGLIBServiceImpl testCGLIBProxy = (TestCGLIBServiceImpl) CGLIBproxy.createProxyInstance(testCGLIB);
testCGLIBProxy.add();
}
}
结果图:

写在后面:spring AOP的两种代理实现代码就写到这,这里只是实现了,如果你要想真正明白,还得熟悉其中原理机制,比如反射机制,newProxyInstance(...),Enhancer()原理,invoke()原理等等。
下一篇将要记录spring AOP的基于注解的具体实现,而对于XML的我姑且不是用了,因为不够灵活,不够强大,要是有时间还会介绍下spring AOP 自定义注解的实现
spring AOP的两种代理的更多相关文章
- JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解
在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...
- (一)spring aop的两种配置方式。
sring aop的方式有两种:(1)xml文件配置方式(2)注解的方式实现,我们可以先通过一个demo认识spring aop的实现,然后再对其进行详细的解释. 一.基于注解的springAop配置 ...
- spring AOP的两种配置方式
连接点(JoinPoint) ,就是spring允许你是通知(Advice)的地方,那可就真多了,基本每个方法的前.后(两者都有也行),或抛出异常是时都可以是连接点,spring只支持方法连接点.其他 ...
- spring aop的两种写法aspect和advisor
本文转自:https://www.cnblogs.com/leiOOlei/p/3709607.html 首先看个例子,如下 接口代码: package com.lei.demo.aop.schema ...
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
第一种代理即Java的动态代理方式上一篇已经分析,在这里不再介绍,现在我们先来了解下GCLIB代理是什么?它又是怎样实现的?和Java动态代理有什么区别? cglib(Code Generation ...
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理-转载
内容是摘抄的,不知最初的原作者,见谅 Java 动态代理.具体有如下四步骤: 通过实现 InvocationHandler 接口创建自己的调用处理器: 通过为 Proxy 类指定 ClassLoade ...
- 使用aspectJ实现Spring AOP的两种方式
方式一:基于aspectJ的XML配置 方式二:基于aspectJ的注解方式 基于aspectJ的XML配置 1) 引入相关jar包 2) 创建Spring核心配置文件,必须导 ...
- spring ----> aop的两种实现方式
实现1:基于xml package com.rr.spring3.interf; //接口 public interface SayHello { public void sayHello(); } ...
- spring AOP的两种配置
xml配置 定义要被代理的方法的接口 public interface TestAop { public void print(String s); } 实现上述接口 public class Tes ...
随机推荐
- 关于MCU的烧录,下载与其他接口的比较(二)
单片机应用系统由硬件和软件组成,软件的载体是硬件的程序存储器,程序存储器采用只读存储器,这种存储器在电源关闭后,仍能保存程序,在系统上电后,CPU可取出这些指令重新执行.只读存储器(Read Only ...
- Delphi Live Bindings 初探
Delphi Live Bindings 初探 Live Bindings,顾名思义,动态绑定. 1.绑定前: 2.点击数据源: 3.绑定连线:点击 蓝色区域, 按住 鼠标左键,一直移动到绿色区域,然 ...
- java中的Iterator和Iterable 区别
java.lang.Iterable java.util.Iterator 来自百度知道: Iterator是迭代器类,而Iterable是接口. 好多类都实现了Iterable接口,这样对象就可以调 ...
- android基础---->发送和接收短信
收发短信应该是每个手机最基本的功能之一了,即使是许多年前的老手机也都会具备这项功能,而Android 作为出色的智能手机操作系统,自然也少不了在这方面的支持.今天我们开始自己创建一个简单的发送和接收短 ...
- java基础---->java输入输出流
今天我们总结一下java中关于输入流和输出流的知识,博客的代码选自Thinking in java一书.我突然很想忘了你,就像从未遇见你. java中的输入流 huhx.txt文件的内容如下: I l ...
- JS-鼠标跟随块(一个小圆点跟着鼠标跑)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- CCNP
CCNP全称是:Cisco Certified Network Professional——思科认证网络高级工程师.CCNP专业人员表示通过认证的人员具有丰富的网络知识.获得CCNP认证的专业人员可以 ...
- [css]演示:纯CSS实现的右侧底部简洁悬浮效果
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta name ...
- for update 和 t.rowid的区别
select * from table_name for update; 和 select t.*, t.rowid from table_name t 的区别 前者会对你查询出来的结果加上锁,而后者 ...
- PHP中文字数限制:中文字符串截取(mb_substr)
一.中文截取:mb_substr() mb_substr( $str, $start, $length, $encoding ) $str,需要截断的字符串 $start,截断开始处,起始处为0 $l ...