一、静态代理实现

  1.接口(抽象主题)

  

  2.接口的实现类(真实主题)

  

  3.代理类(代理主题)

  

  4.测试类:

     ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        ProxySubject proxySubject =(ProxySubject) context.getBean("proxySubject");
        proxySubject.doSome();

二、JDK动态代理

  JDK动态代理所用到的代理类在程序调用到代理类对象时才由JVM真正创建,JVM根据传进来的 业务实现类对象 以及 方法名 ,动态地创建了一个代理类的class文件并被字节码引擎执行,然后通过该代理类对象进行方法调用。

  1.抽象主题,真实主题与上面一致

  2.动态代理类

package com.cmy.handler;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DoSomeBeanFactory implements InvocationHandler {
    private Object target;//这其实业务实现类对象,用来调用具体的业务方法

    public Object bind(Object target) {
        this.target = target;  //接收业务实现类对象参数

        //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
        //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置=====");
        //调用真正的业务方法
        Object result = method.invoke(target, args);
        System.out.println("后置=====");
        return result;
    }
}

  3.测试类

public class ProxyDemo {
    public static void main(String[] args) {
         //创建业务类对象
         Subject subject=new ReallySubject();
         //创建代理对象
         DoSomeBeanFactory factory=new DoSomeBeanFactory();
         //调用bind方法获取代理对象
         Subject proxy = (Subject)factory.bind(subject);
         //调用目标函数
         proxy.say();
    }
}

三、Cglib动态代理

   cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。

  新建代理类

package com.cmy.handler;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class DoSomeBeanCGlib implements MethodInterceptor{
    private Object target;//业务类对象,供代理方法中进行真正的业务方法调用

    //相当于JDK动态代理中的绑定
    public Object getInstance(Object target) {
        this.target = target;  //给业务对象赋值
        Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
        enhancer.setSuperclass(this.target.getClass());  //为加强器指

    //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实    现intercept()方法进行拦
        enhancer.setCallback(this);
        // 创建动态代理类对象并返回
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("预处理——————");
        methodProxy.invokeSuper(o, objects); //调用业务类(父类中)的方法
        System.out.println("调用后操作——————");
        return null;
    }
}

  总结:

  • JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;
  • CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;
  • 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
  • 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
  • [aop:config proxy-target-class="true"] 强制切换成CGLIB动态代理
  • 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

Spring——代理实现AOP的更多相关文章

  1. spring 代理注解 <aop:aspectj-autoproxy />

    spring默认使用jdk的代理方式,使用jdk的代理方式我们知道,代理的类需要实现一个接口,若果没有就会报,java.lang.NoSuchMethodException: com.sun.prox ...

  2. Spring学习总结(二)——静态代理、JDK与CGLIB动态代理、AOP+IoC

    一.为什么需要代理模式 假设需实现一个计算的类Math.完成加.减.乘.除功能,如下所示: package com.zhangguo.Spring041.aop01; public class Mat ...

  3. Spring 代理对象,cglib,jdk的问题思考,AOP 配置注解拦截 的一些问题.为什么不要注解在接口,以及抽象方法.

    可以被继承 首先注解在类上是可以被继承的 在注解上用@Inherited /** * Created by laizhenwei on 17:49 2017-10-14 */ @Target({Ele ...

  4. 8 -- 深入使用Spring -- 4...6 AOP代理:基于注解的XML配置文件的管理方式

    8.4.6 基于XML配置文件的管理方式 Spring 2.x 提供一个新的aop:命名空间来定义切面.切入点和增强处理. XML配置方式优点: ⊙ 如果应用没有使用JDK 1.5 以上版本,那么应用 ...

  5. 2018.12.24 Spring中的aop演示(也就是运用aop技术实现代理模式)

    Aop的最大意义是:在不改变原来代码的前提下,也不对源代码做任何协议接口要求.而实现了类似插件的方式,来修改源代码,给源代码插入新的执行代码. 1.spring中的aop演示 aop:面向方面编程.不 ...

  6. spring (反射+代理+DI+AOP)

    spring  https://baijiahao.baidu.com/s?id=1620606848227713760&wfr=spider&for=pc 反射 https://bl ...

  7. 这一次搞懂Spring代理创建及AOP链式调用过程

    文章目录 前言 正文 基本概念 代理对象的创建 小结 AOP链式调用 AOP扩展知识 一.自定义全局拦截器Interceptor 二.循环依赖三级缓存存在的必要性 三.如何在Bean创建之前提前创建代 ...

  8. 使用Java原生代理实现AOP

    ### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...

  9. Spring 3.0 AOP (一)AOP 术语

    关于AOP.之前我已写过一个系列的随笔: <自己实现简单的AOP>,它的关注点在于实现.实现语言是C#,实现方式为 自定义实现 RealProxy 抽象类.重写Invoke方法,以便进行方 ...

随机推荐

  1. win10 Snipaste 截图软件

    安装教程:搜索 snipaste,网上可以直接下载 使用教程: 1)截图按钮:F1 2)粘贴按钮:F3

  2. Java EE javax.servlet.http中的HttpRequest抽象类

    HttpRequest抽象类 public abstract class HttpServlet extends GenericServlet 实现的接口有:Serializable, Servlet ...

  3. ccpc湘潭邀请赛 Partial Sum

    选定最多m的区间,使区间和的绝对值最大.但是左右端点不能重复选取 首先涉及到区间和的问题,就应该想到用前缀和去优化 这里对前缀和排序 然后贪心的去选取最大.次大 (比赛的时候脑子堵的很,没想出来 可惜 ...

  4. 解决maven依赖包下载慢的问题

    修改maven 目录下setting.xml配置文件 在mirrors中添加如下配置即可 <mirror> <id>alimaven</id> <name&g ...

  5. R语言学习笔记:读取前n行数据

    常规读取 一般我们读取文件时都会读取全部的文件然后再进行操作,因为R是基于内存进行计算的. data <- read.table("C:\\Users\\Hider\\Desktop\ ...

  6. Docker 容器数据卷(Data Volume)与数据管理

    卷(Volume)是容器中的一个数据挂载点,卷可以绕过联合文件系统,从而为Docker 提供持久数据,所提供的数据还可以在宿主机-容器或多个容器之间共享.通过卷,我们可以可以使修改数据直接生效,而不必 ...

  7. current status of the installation and the internationalization of Samba 3.0

    Only about 8 months from release of Samba 3.0.0, there is beginning to be the transition from 2.2.x. ...

  8. SAP笔记

    1,负数的表示增强 负号从数字后更改到数字前面 适用于字符型字段: CALL FUNCTION 'CLOI_PUT_SIGN_IN_FRONT' CHANGING VALUE = gt_table-c ...

  9. Vim——替换命令

     原创声明:本文系博主原创文章,转载或引用请注明出处. 1. 文本替换 #替换每一行的第一个a :%s/a/b/ #全部替换 :%s/a/b/g #替换/时需要转义"\/" 2. ...

  10. webpack拷贝插件 copy-webpack-plugin

    copy-webpack-plugin 安装 npm install --save-dev copy-webpack-plugin 作用:在webpack中拷贝文件和文件夹 from 定义要拷贝的源文 ...