动态代理和Spring Aop
1.动态代理
在静态代理中,每个被代理的类都需要单独定义一个代理类,当业务庞大时,代理类的代码也会很庞大,造成重复代码很多,不好维护。
相对于静态代理而言,动态代理可以将代理类的代码集中起来,让同一个类的不同方法,不同类的不同方法都会汇集在一起,方便对一些业务逻辑进行集中处理。
例如:https://www.zhihu.com/question/20794107/answer/75164285
1.1 JDK的动态代理
JDK的动态代理可以基于 java.lang.reflect.InvocationHandler定义,举例说明
1.创建一个接口
public interface StudentInterface {
public void goToSchool();
}
2.创建一个InvocationHandler. 如果接口有实现类,可以在创建InvocationHandler的时候传一个实现类的对象
public class StudentInvocationHandler implements InvocationHandler {
private Object target;
public StudentInvocationHandler(){}
public StudentInvocationHandler(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//method.invoke(target, args); //执行被代理的对象的方法
System.out.println("这是InvocationHandler中的invoke方法!");
return null;
}
}
3. 创建代理类
InvocationHandler invocationHandler = new StudentInvocationHandler();
StudentInterface studentInterface = (StudentInterface) Proxy.newProxyInstance
(StudentInterface.class.getClassLoader(),
new Class[]{StudentInterface.class}, invocationHandler);
studentInterface.goToSchool();
例子中没有写StudentInterface接口的实现类,但是却可以通过动态代理创建 StudentInterface对象,其实Mybatis的Mapper接口就是这样的,编程的时候没有实现Mapper接口,但是却可以获取到Mapper接口的对象,其实真正获取到的对象就是代理对象.
调用studentInterface的所有方法都会跳到 StudentInvocationHandler 的 invoke方法中,可以在invoke方法中编写自己的业务逻辑。
如2中所说,可以在创建InvocationHandler的时候传入 实现类的对象,然后就可以在invoke方法中执行被代理的对象的方法。
1.2 基于cglib的动态代理
1.创建 MethodInterceptor
public class StudentCglib implements MethodInterceptor {
private Object target;
public StudentCglib(Object target){
this.target = target;
}
public StudentCglib(){}
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("到了MethodInterceptor的 intercept方法, 这是基于cglib的动态代理");
//method.invoke(target, objects);
return null;
}
public Object getInstance(Class originClass){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(originClass);
enhancer.setCallback(this);
return enhancer.create();
}
}
2.创建代理类
StudentCglib studentCglib = new StudentCglib();
StudentInterface studentProxy = (StudentInterface)
studentCglib.getInstance(StudentInterface.class);
studentProxy.goToSchool();
代理类实际上是 在 MethodInterceptor 中的 getInstance方法中用 Enhancer创建的,参数没有限制必须要是接口,所以是不必基于接口的。
2.Spring Aop
spring的Aop其实就是基于动态代理的,动态代理可以实现将分散的代码集中,和Aop的思想是一致的。
Spring 可以在配置文件中利用aop标签进行配置,还可以基于aspectj,在java代码中进行配置,这种方法更加简洁明了。
利用aspectj配置时,注意要在配置文件中加上
<aop:aspectj-autoproxy/>
Spring在创建代理对象的时候,会判断被代理的类时候实现了接口,如果实现了接口就使用JDK的动态代理,否则就使用cglib的动态代理。
org.springframework.aop.framework.DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
- 微信JSSDK分享到朋友圈和朋友自定义内容功能实现
- 无线安全渗透测试套件WiFi-Pumpkin新版本发布
- Java使用QQ邮箱给其他邮箱发邮件
- 从wireshark抓包开始学习https
- 用于时间序列预测的Python环境
- Pandoc安装实现Markdown转PDF (CentOS6)
- String类replaceAll方法正则替换深入分析
- 微信硬件平台对接--蓝牙
- 初试git+github(linux环境)
- Raspberry PI Nginx 安装
- 微信支付-Java-SpringMVC基础一些代码支持
- 使用Kafka的High Level Consumer
- 微信公众号发送模板消息 Java实现。
- [Intellij IDEA]File size exceeds configured limit
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 原创 | 险些翻车,差一点没做出来的基础算法题
- 原创 | 你追我,如果你追到我……那就算你赢了
- 原创 | 详解gitignore的使用方法,让你尽情使用git add .
- 第31天:面试比 KMP 还容易被问到的匹配算法!
- 原创 | 深度学习开篇,来聊聊感知机的原理
- 算法题:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
- 使用Java和Python解题:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
- R语言中%||%是什么意思?
- 原创 | 你会用缓存吗?详解LRU缓存淘汰算法
- 用Java实现:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。
- Hacking with iOS: SwiftUI Edition - Hot Prospects项目(一)
- 原创 | 详解command设计模式,解耦操作和回滚
- 第32天:图解大数打印,这道题如此经典!
- Mac终端配置好的环境变量在关闭终端后失效怎么办
- R中的stack和unstack函数