>AOP基本概念

  1)通知(Advice):织入到目标类连接点上的一段程序代码。通知分为五种类型:

  - Before:在方法被调用之前调用

  - After:在方法完成后调用通知,无论方法是否执行成功

  - After-returning:在方法成功执行之后调用通知

  - After-throwing:在方法抛出异常后调用通知

  - Around:通知了好、包含了被通知的方法,在被通知的方法调用之前后调用之后执行自定义的行为

  2)切点(Pointcut):AOP通过“切点”定位特定的连接点

  3)连接点(Joinpoint):程序执行的某个特定位置:如类开始初始化前、类初始化后、类某个方法调用前、调用后、方法抛出异常后。这些代码中的特定点,称为“连接点”。

  4) 织入(Weaving):织入是将增强添加到目标类具体连接点上的过程。AOP有三种织入方式:

  - 编译期织入,这要求使用特殊的Java编译器;

  - 类装载期织入,这要求使用特殊的类装载器;

  - 动态代理织入,在运行期为目标类添加增强生成子类的方式。

  Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。

  5)切面(Aspect)切面由切点和通知组成,它既包括了横切逻辑的定义,也包括了连接点的定义

  Spring 是切片流程

  代理模式

  就好比明星和经纪人,经纪人负责接活,负责明星唱歌前会场准备,明星唱歌后收钱。 代理类其实就是在代理对象,前后做了一些其他的处理, 这已经具备 AOP的轮廓了

  静态代理模式栗子

  // 接口

  public interface IUserDao {

  void save();

  void find();

  }

  // 目标对象

  public class UserDao implements IUserDao {

  @Override

  public void save() {

  System.out.println("模拟:保存用户!");

  }

  @Override

  public void find() {

  System.out.println("模拟:查询用户");

  }

  }

  /**

  * 静态代理 特点:

  * 1. 目标对象必须要实现接口

  * 2. 代理对象,要实现与目标对象一样的接口

  */

  public class UserDaoProxy implements IUserDao {

  // 代理对象,需要维护一个目标对象

  private IUserDao target = new UserDao();

  @Override

  public void save() {

  System.out.println("代理操作: 开启事务...");

  target.save(); // 执行目标对象的方法

  System.out.println("代理操作:提交事务...");

  }

  @Override

  public void find() {

  target.find();

  }

  }

  public class StaticProxyTest {

  /**

  * @param args

  */

  public static void main(String[] args) {

  IUserDao proxy = new UserDaoProxy();

  proxy.save();

  }

  }

  可以看到,静态代理是必须要有接口的,代理类和目标类都得事先接口,这样就显得很麻烦了,每次代理一个目标对象,就得做一个代理类,有没有一种方式,可以使用一个代理 ,代理多个目标对象呢?

  动态代理模式栗子

  动态代理不需要提前建立代理,而是在运行时,为目标对象动态生成代理类

  // 接口

  public interface IUserDao {

  void save();

  void find();

  }

  // 目标对象

  public class UserDao implements IUserDao {

  @Override

  public void save() {

  System.out.println("模拟: 保存用户!");

  }

  @Override

  public void find() {

  System.out.println("查询");

  }

  }

  /**

  * 动态代理:JDK 动态代理采用的是反射机制实现

  * 代理工厂,给多个目标对象生成代理对象!

  *

  */

  public class ProxyFactory {

  // 接收一个目标对象

  private Object target;

  public ProxyFactory(Object target) {

  this.target = target;

  }

  // 返回对目标对象(target)代理后的对象(proxy)

  public Object getProxyInstance() {

  Object proxy = Proxy.newProxyInstance(

  target.getClass().getClassLoader(), // 目标对象使用的类加载器

  target.getClass().getInterfaces(), // 目标对象实现的所有接口

  new InvocationHandler() { // 执行代理对象方法时候触发

  @Override

  public Object invoke(Object proxy, Method method, Object[] args)

  throws Throwable {

  // 获取当前执行的方法的方法名

  String methodName = method.getName();

  // 方法返回值

  Object result = null;

  if ("find".equals(methodName)) {

  // 直接调用目标对象方法

  result = method.invoke(target, args);

  } else {

  System.out.println("开启事务...");

  // 执行目标对象方法

  result = method.invoke(target, args);

  System.out.println("提交事务...");

  }

  return result;

  }

  }

  );

  return proxy;

  }

  }

  public class JDKDynamicProxyTest {

  /**

  * @param args

  */

  public static void main(String[] args) {

  // 目标对象

  IUserDao target = new UserDao();

  // 创建代理类

  IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();

  System.out.println("代理对象: "+proxy.getClass());

  proxy.save();

  }

  }

  静态代理动态代理总结

  可以总结一下,JDK 动态代理

  // 创建代理类

  IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();

  实际上 隐藏了动态的去实现 目标对象的一个接口

  class $jdkProxy implements IUserDao{}

  也就是说 使用JDK 反射方式实现动态代理,目标对象必须实现一个接口,这就可能出现问题了,假设一个类,就是没有实现接口怎么办?

  CGLIB实现动态代理实现栗子

  CGLIB是使用继承的方式动态生成代理类,这个代理类是继承目标类的,这个就有个问题,需要目标类不被final修饰。

  有点类似

  public class UserDao{}

  // CGLIB 是以动态生成的子类继承目标的方式实现,程序执行时,隐藏了下面的过程

  public class $Cglib_Proxy_class extends UserDao{}

  CGLIB实现

  // 目标对象

  public class UserDao {

  public void save() {

  System.out.println("模拟: 保存用户!");

  }

  public void find() {

  System.out.println("查询");

  }

  }

  public class CGLIBProxyFactory {

  static class SimpleInterceptor implements MethodInterceptor {

  /**

  * @see org.springframework.cglib.proxy.MethodInterceptor#intercept(java.lang.Object,

  * java.lang.reflect.Method, java.lang.Object[],

  * org.springframework.cglib.proxy.MethodProxy)

  */

  @Override

  public Object intercept(Object target, Method methmod, Object[] args, MethodProxy proxy) throws Throwable {

  System.out.println("entering " + methmod.getName());

  Object result = proxy.invokeSuper(target, args);

  System.out.println("leveaing " + methmod.getName());

  return result;

  }

  }

  public static T getProxy(Class cls) {

  Enhancer enhancer = new Enhancer();

  // 继承目标类

  enhancer.setSuperclass(cls);

  enhancer.setCallback(new SimpleInterceptor());

  return (T) enhancer.create();

  }

  }

  public class CGLIBProxyTest {

  public static void main(String[] args) {

  //生成代理 没有接口

  UserDao proxy = (UserDao) CGLIBProxyFactory.getProxy(UserDao.class);

  System.out.println("代理类:"+ proxy.getClass());

  proxy.save();

  }

  }无锡正规妇科医院 http://www.jlfukeyy.com/

  JDK和CGLIB的区别

  1.上面可以可以看到 CGLIB是不需要 目标对象实现接口的, CGLIB是通过继承来实现的

  2. JDK动态代理是需要一个具体的目标对象的,但是CGLIB是不需要这么一个具体对象的

  Spring AOP 是怎样实现的呢?

  1.AOP 是基于动态代理模式

  2.AOP是方法级别的

  3.AOP可以分类业务代码和关注点代码(日志,事务等)

  AOP 是什么时候生成代理的?

  AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表;而动态代理则以 Spring AOP 为代表

  IOC容器BeanDefinitionMap里面结构看内容是啥

  bean: class [org.springframework.aop.aspectj.AspectJPointcutAdvisor];

  scope=;

  abstract=false;

  lazyInit=false;

  autowireMode=0;

  dependencyCheck=0;

  autowireCandidate=true;

  primary=false;

  factoryBeanName=null;

  factoryMethodName=null;

  initMethodName=null;

  destroyMethodName=null,

  org.springframework.aop.aspectj.AspectJPointcutAdvisor#2=Root

  bean: class [org.springframework.aop.aspectj.AspectJPointcutAdvisor];

  scope=;

  abstract=false;

  lazyInit=false;

  autowireMode=0;

  dependencyCheck=0;

  autowireCandidate=true;

  primary=false;

  factoryBeanName=null;

  factoryMethodName=null;

  initMethodName=null;

  destroyMethodName=null,

  org.springframework.aop.aspectj.AspectJPointcutAdvisor#3=Root

  bean:class [org.springframework.aop.aspectj.AspectJPointcutAdvisor];

  scope=;

  abstract=false;

  lazyInit=false;

  autowireMode=0;

  dependencyCheck=0;

  autowireCandidate=true;

  primary=false;

  factoryBeanName=null;

  factoryMethodName=null;

  initMethodName=null;

  destroyMethodName=null,

  org.springframework.aop.aspectj.AspectJPointcutAdvisor#0=Root

Spring AOP 原理的理解的更多相关文章

  1. 面试问烂的 Spring AOP 原理、SpringMVC 过程(求求你别问了)

    Spring AOP ,SpringMVC ,这两个应该是国内面试必问题,网上有很多答案,其实背背就可以.但今天笔者带大家一起深入浅出源码,看看他的原理.以期让印象更加深刻,面试的时候游刃有余. Sp ...

  2. Spring学习总结(1)——Spring AOP的概念理解

    1.我所知道的aop 初看aop,上来就是一大堆术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充等等.一下子让你不知所措,心想着:怪不得 很多人都和我说aop多难多难 .当我看进去 ...

  3. spring aop原理分析

    持续更新... aop跟java代理模式有关. java.lang.reflect.Proxy java.lang.reflect.InvocationHandler 工厂模式用到java反射. ao ...

  4. aop原理及理解

    概念 Aspect Oriented Programming,面向切面编程,实际上它是一个规范.一种设计思路,总之是抽象的. 先上图 使用目的 从项目结构上来说 对业务逻辑的各个部分进行隔离,降低业务 ...

  5. Spring AOP原理(续)

    十二.AOP 1. 说出Spring的通知类型有哪些? spring共提供了五种类型的通知: 通知类型 接口 描述 Around 环绕通知 org.aopalliance.intercept.Meth ...

  6. Spring Boot -- Spring AOP原理及简单实现

    一.AOP基本概念 什么是AOP,AOP英语全名就是Aspect oriented programming,字面意思就是面向切面编程.面向切面的编程是对面向对象编程的补充,面向对象的编程核心模块是类, ...

  7. spring ioc 原理 spring aop原理

    大家一直都说spring的IOC如何如何的强大,其实我倒觉得不是IOC如何的强大,说白了IOC其实也非常的简单.我们先从IOC说起,这个概念其实是从我们平常new一个对象的对立面来说的,我们平常使用对 ...

  8. spring aop 原理学习

    @EnableAspectJAutoProxy: @Import(AspectJAutoProxyRegistrar.class) 实际是创建了一个以org.springframework.aop.c ...

  9. spring aop原理和实现

    一.aop是什么 1.AOP面向方面编程基于IoC,是对OOP的有益补充: 2.AOP利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了 多个类的公共行为封装到一个可 ...

随机推荐

  1. Linux下的IO监控与分析(转)

    各种IO监视工具在Linux IO 体系结构中的位置 源自 Linux Performance and Tuning Guidelines.pdf 1 系统级IO监控 iostat iostat -x ...

  2. 推荐一个web字体转换工具TTF转SVG

    推荐一个web字体转换工具:https://www.fontsquirrel.com/tools/webfont-generator

  3. Nginx之Rewrite规则

    IF语句: http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_rewrite_module.html#if 首先申明nginx只有i ...

  4. javascript常用方法 - String

    // 1.长字符串 // 1.1 let longString1 = "This is a very long string which needs " + "to wr ...

  5. canvas笔记备忘

    备忘 1. canvas标签的宽和高设置是标签属性设置, 不是 css 属性设置. 如果用 css 属性设置大小, canvas 会被拉伸. 标签属性例如: class, id, style, wid ...

  6. spring cloud java: 无法访问redis.clients.jedis.JedisPoolConfig 找不到redis.clients.jedis.JedisPoolConfig的类文件

    spring cloud <spring-cloud.version>Greenwich.SR3</spring-cloud.version> 注入Redis 时候: @Bea ...

  7. Java 学习大纲

    1.java基础 1.1 Collection和Map     (1)掌握Collection和Map的继承体系     (2)掌握ArrayList,LinkedList,Vector,Stack, ...

  8. 僵尸进程bug排除方法

    多进程处理存在的问题 直接return 200 子进程 signal.signal(signal.SIGCHLD, signal.SIG_IGN) #不管子进程,不然R的多进程切图会产生僵尸进程

  9. SQL Server PARTITION FUNCTION(分区)

    分区并不影响Linq,sql查询 在MSSQL中,选中目标表,右键-存储-创建分区 根据提示完成分区,存储成sql 这里展示如何根据Id的数据范围分区 在执行前,可能需要设置日志文件大小为" ...

  10. 【Docker学习之七】Docker图形化管理和监控

    环境 docker-ce-19.03.1-3.el7.x86_64 centos 7 一.Docker管理工具 (官方三剑客)1.Docker Machine(学习的Openstack Heat)Cr ...