笔记

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的更多相关文章

  1. CgLib动态代理学习【Spring AOP基础之一】

    如果不了解JDK中proxy动态代理机制的可以先查看上篇文章的内容:Java动态代理学习[Spring AOP基础之一] 由于Java动态代理Proxy.newProxyInstance()的时候会发 ...

  2. 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  3. Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。

    借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...

  4. Spring-Boot的动态代理AOP原理

    前言 Spring AOP使用了动态代理技术,动态代理在业界比较流行的实现方式有,CGLIB,Javassist,ASM等等. Spring动态代理实现方式 Spring采用了JDK和CGLIB两种方 ...

  5. 浅析DispatchProxy动态代理AOP

    浅析DispatchProxy动态代理AOP(代码源码) 最近学习了一段时间Java,了解到Java实现动态代理AOP主要分为两种方式JDK.CGLIB,我之前使用NET实现AOP切面编程,会用Fil ...

  6. Java动态代理学习【Spring AOP基础之一】

    Spring AOP使用的其中一个底层技术就是Java的动态代理技术.Java的动态代理技术主要围绕两个类进行的 java.lang.reflect.InvocationHandler java.la ...

  7. 动态代理以及对应Spring中AOP源码分析

    AOP(面向切面编程)在Spring中是被广泛应用的(例如日志,事务,权限等),而它的基本原理便是动态代理. 我们知道动态代理有两种:基于JDK的动态代理以及基于CGlib动态代理.以下是两种动态代理 ...

  8. spring中使用动态代理(AOP)

    spring是整合了BGLIB和JDK两种动态代理 示例:使用CGLIB代理 public class MyCar { private String color = "blue"; ...

  9. [转]JAVA的动态代理机制及Spring的实现方式

    JAVA 代理实现 代理的实现分动态代理和静态代理,静态代理的实现是对已经生成了的JAVA类进行封装. 动态代理则是在运行时生成了相关代理累,在JAVA中生成动态代理一般有两种方式. JDK自带实现方 ...

  10. 动态代理 aop切面实现事务管理

    1.定义接口和实现 public interface UserService { public String getName(int id); public Integer getAge(int id ...

随机推荐

  1. 【PAT甲级】1042 Shuffling Machine (20 分)

    题意: 输入洗牌次数K(<=20),输入54张牌每次洗入的位置(不是交换的位置),输出洗好的牌. AAAAAccepted code: #define HAVE_STRUCT_TIMESPEC ...

  2. 验证码校验(Ajax)

    show.jsp <%@ page language="java" contentType="text/html; charset=utf-8" page ...

  3. Java笔记---成员初始化

    成员初始化 成员初始化 Java尽力保证所有变量可以在使用前可以初始化. void f(){ int i; System.out.println(i); //! i++; //开幕雷击:这里就报错了, ...

  4. Swift3.0-基础知识

    本文对Swift做一个从OC的角度的基础知识简单概要. Swift OC 说明 let.var const 在OC中不用const声明的常量,都认为是变量 Float.Double CGFloat   ...

  5. pytest框架,使用print在控制台输入

    代码示例: import pytest@pytest.fixture(autouse=True,scope='session') #autouse=True,scope='session'def se ...

  6. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:可滚动

    <!DOCTYPE html> <html> <head> <title>菜鸟教程(runoob.com)</title> <meta ...

  7. ANSYS-MFC二次开发

    目录 1. 开发流程 2. 开发代码 1. 开发流程 ANSYS-MFC二次开发的思路其实是特别简单的,通常MFC主要是设计界面,然后从MFC界面中读取要设计的参数,然后根据这些设置了的参数生成APD ...

  8. Spring boot 中发送邮件

    参考:https://blog.csdn.net/qq_39241443/article/details/81293939 添加依赖: <dependency> <groupId&g ...

  9. Python组合类型笔记

    Python中常用的三种组合数据类型,分别是: - 集合类型 - 序列类型 - 字典类型 1. 集合类型: -集合用大括号{}表示,元素间用逗号分隔 -建立集合类型用{}或set() -建立空集合类型 ...

  10. 【转】android之在activity中控制另一个activity的UI更新_如何在activity之间传递handler

    来自:http://blog.csdn.net/jason0539/article/details/18055259 遇到一个问题,需要在一个activity中控制另一个acitivity做一些更新, ...