动态代理,AOP和Spring
笔记
1. 什么是AOP?
Aspect-Oriented Programming 面向切面编程,关注一个统一的切面,相对于OOP(面向对象编程)。
适合的场景:
- 日志
- 缓存
- 鉴权
如果用OOP来做怎么办?
- 装饰器模式
2. 装饰器模式 (OOP, 静态代理)
Decorator pattern:
动态地为一个对象增加功能,但是不改其结构。
public interface DataService {
String a(int i);
String b(int i);
}
public class DataServiceImpl implements DataService {
@Override
public String a(int i) {
return UUID.randomUUID().toString();
}
@Override
public String b(int i) {
return UUID.randomUUID().toString();
}
}
public class Main {
static DataService service = new CacheDecorator(new LogDecorator(new DataServiceImpl()));
public static void main(String[] args) {
System.out.println(service.a(1));
System.out.println(service.b(1));
}
}
假如是class,就会有浪费。
3. AOP动态代理
public class LogProxy implements InvocationHandler {
private DataService delegate;
public LogProxy(DataService delegate) {
this.delegate = delegate;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + " is invoker " + Arrays.toString(args));
Object result = method.invoke(delegate, args);
System.out.println(method.getName() + " is finished: " + result);
return result;
}
}
public class Main {
static DataService service = new DataServiceImpl();
public static void main(String[] args) {
DataService dataService = (DataService) Proxy.newProxyInstance(
service.getClass().getClassLoader(),
new Class[]{DataService.class},
new LogProxy(service));
dataService.a(1);
dataService.b(3);
}
}
优点:方便,不需要依赖任何第三方库
缺点:功能受限,只能用于接口 (源代码中接收参数为interface,如果是class会报异常)
4. 如果是class怎么办?
CGLIB/ByteBuddy字节码生成
public class Main {
static DataServiceImpl service = new DataServiceImpl();
public static class LogInterceptor implements MethodInterceptor {
private DataServiceImpl delegate;
public LogInterceptor(DataServiceImpl delegate) {
this.delegate = delegate;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(method.getName() + " is invoker " + Arrays.toString(objects));
Object result = method.invoke(delegate, objects);
System.out.println(method.getName() + " is finished: " + result);
return result;
}
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(DataServiceImpl.class);
enhancer.setCallback(new LogInterceptor(service));
DataServiceImpl enhancedService = (DataServiceImpl) enhancer.create();
enhancedService.a(1);
enhancedService.b(2);
}
// 这里会动态生成一个叫做DataServiceImpl$$EnhancerByCGLIB$$9bce1175@651的类,它是动态生成出来,并且是继承我们的DataServiceImpl的。
优点:强大,不受接口的限制
缺点:需要额外引用第三方库,不能增强final类/final/private方法(因为原理是继承)。
动态代理,AOP和Spring的更多相关文章
- CgLib动态代理学习【Spring AOP基础之一】
如果不了解JDK中proxy动态代理机制的可以先查看上篇文章的内容:Java动态代理学习[Spring AOP基础之一] 由于Java动态代理Proxy.newProxyInstance()的时候会发 ...
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
- Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。
借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...
- Spring-Boot的动态代理AOP原理
前言 Spring AOP使用了动态代理技术,动态代理在业界比较流行的实现方式有,CGLIB,Javassist,ASM等等. Spring动态代理实现方式 Spring采用了JDK和CGLIB两种方 ...
- 浅析DispatchProxy动态代理AOP
浅析DispatchProxy动态代理AOP(代码源码) 最近学习了一段时间Java,了解到Java实现动态代理AOP主要分为两种方式JDK.CGLIB,我之前使用NET实现AOP切面编程,会用Fil ...
- Java动态代理学习【Spring AOP基础之一】
Spring AOP使用的其中一个底层技术就是Java的动态代理技术.Java的动态代理技术主要围绕两个类进行的 java.lang.reflect.InvocationHandler java.la ...
- 动态代理以及对应Spring中AOP源码分析
AOP(面向切面编程)在Spring中是被广泛应用的(例如日志,事务,权限等),而它的基本原理便是动态代理. 我们知道动态代理有两种:基于JDK的动态代理以及基于CGlib动态代理.以下是两种动态代理 ...
- spring中使用动态代理(AOP)
spring是整合了BGLIB和JDK两种动态代理 示例:使用CGLIB代理 public class MyCar { private String color = "blue"; ...
- [转]JAVA的动态代理机制及Spring的实现方式
JAVA 代理实现 代理的实现分动态代理和静态代理,静态代理的实现是对已经生成了的JAVA类进行封装. 动态代理则是在运行时生成了相关代理累,在JAVA中生成动态代理一般有两种方式. JDK自带实现方 ...
- 动态代理 aop切面实现事务管理
1.定义接口和实现 public interface UserService { public String getName(int id); public Integer getAge(int id ...
随机推荐
- 【PAT甲级】1042 Shuffling Machine (20 分)
题意: 输入洗牌次数K(<=20),输入54张牌每次洗入的位置(不是交换的位置),输出洗好的牌. AAAAAccepted code: #define HAVE_STRUCT_TIMESPEC ...
- 验证码校验(Ajax)
show.jsp <%@ page language="java" contentType="text/html; charset=utf-8" page ...
- Java笔记---成员初始化
成员初始化 成员初始化 Java尽力保证所有变量可以在使用前可以初始化. void f(){ int i; System.out.println(i); //! i++; //开幕雷击:这里就报错了, ...
- Swift3.0-基础知识
本文对Swift做一个从OC的角度的基础知识简单概要. Swift OC 说明 let.var const 在OC中不用const声明的常量,都认为是变量 Float.Double CGFloat ...
- pytest框架,使用print在控制台输入
代码示例: import pytest@pytest.fixture(autouse=True,scope='session') #autouse=True,scope='session'def se ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:可滚动
<!DOCTYPE html> <html> <head> <title>菜鸟教程(runoob.com)</title> <meta ...
- ANSYS-MFC二次开发
目录 1. 开发流程 2. 开发代码 1. 开发流程 ANSYS-MFC二次开发的思路其实是特别简单的,通常MFC主要是设计界面,然后从MFC界面中读取要设计的参数,然后根据这些设置了的参数生成APD ...
- Spring boot 中发送邮件
参考:https://blog.csdn.net/qq_39241443/article/details/81293939 添加依赖: <dependency> <groupId&g ...
- Python组合类型笔记
Python中常用的三种组合数据类型,分别是: - 集合类型 - 序列类型 - 字典类型 1. 集合类型: -集合用大括号{}表示,元素间用逗号分隔 -建立集合类型用{}或set() -建立空集合类型 ...
- 【转】android之在activity中控制另一个activity的UI更新_如何在activity之间传递handler
来自:http://blog.csdn.net/jason0539/article/details/18055259 遇到一个问题,需要在一个activity中控制另一个acitivity做一些更新, ...