一.AOP的概念

 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

二.主要用途

将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

  三.代理

 AOP的实现关键在于AOP框架自动创建的AOP代理。AOP代理主要分为两大类:

         1.静态代理:使用AOP框架提供的命令进行编译,从而在编译阶段就可以生成AOP代理类,因此也称为编译时增强;静态代理一Aspectj为代表。

         2.动态代理:在运行时借助于JDK动态代理,CGLIB等在内存中临时生成AOP动态代理类,因此也被称为运行时增强,Spring AOP用的就是动态代理。

         那么其实在Spring框架中用到就是JDK动态代理或者是CGLIB代理。

四.JDK动态代理

        JDK动态代理用到了一个类Proxy,下面举个例子来说明一下,Proxy这个类是如何实现JDK的动态代理的。

          有一个需求就是,当用户名为空的时候,不能调用业务方法,当用户名不为空是可以调用业务方法。

          1.新建一个业务接口,并书写业务方法。

           

package cn.service;

public interface DoService {
    //添加
    public void  add();
    //查询
    public void selectInfo();
    //更新
    public void update();
}

2.新建一个业务接口实现类

package cn.service.impl;

import cn.service.DoService;

public class DoServiceImpl implements DoService{

    //用户名
    private String userName;

    @Override
    public void add() {
        System.out.println("添加的方法");

    }

    @Override
    public void selectInfo() {
        System.out.println("查询的方法");

    }

    @Override
    public void update() {
        System.out.println("更新的方法");
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}

 一般如果我们需要进行这样一个业务需求我们会相到 一个办法就是在所有的方法中进行一个判断就是判读用户名是否为空,显然这样很麻烦,所有我们用到了JDK动态代理,主函数 -->代理-->目标对象的方法。这样,以后不管是修改判断条件,还是查找等,可以直接在代理类中进行处理。

           

3.创建代理对象工厂类

         

package cn.aop;

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

import cn.service.impl.DoServiceImpl;

/**
 * 代理工厂类
 * @author hyj
 *
 */
public class JDKProxyFactory implements InvocationHandler{
    //要返回的代理对象
   private Object obj;
   /**
    * 通过代理工厂的方式来创建代理类
    * @param obj  要代理的类的对象
    * @return
    */
   public Object createProxyIntance(Object obj){
       this.obj=obj;
       //第一个参数是目标对象的类加载器
       //第二个参数是目标对象实现的接口
       //第三个参数传入一个InvocationHandler实例,该参数和回调有关系。
       return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),this);

   }
   @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
       Object proxyObject=null;
       DoServiceImpl ds=(DoServiceImpl)obj;
       if(ds.getUserName()!=null){
           proxyObject= method.invoke(ds, args);
       }else{
           System.out.println("用户名为空,已拦截");
       }
        return proxyObject;
    }
    public Object getObj() {
        return obj;
    }
    public void setObj(Object obj) {
        this.obj = obj;
    }

}

4.测试类

package cn.test;

import cn.aop.JDKProxyFactory;
import cn.service.DoService;
import cn.service.impl.DoServiceImpl;

public class TestHappy {
   public static void main(String[] args) {
      JDKProxyFactory jpf=new JDKProxyFactory();
      DoService ds=(DoService)jpf.createProxyIntance(new DoServiceImpl("fsf"));
      ds.selectInfo();
   }
}

     步骤:

  • 首先调用代理工厂的createProxyIntance(Object obj)创建DoServiceImpl类的代理类.
  • 在该方法内,调用Proxy.newProxyInstance()方法创建代理对象。第一个参数是目标对象的类加载器,第二个参数是目标对象实现的接口,第三个参数传入一个InvocationHandler实例,该参数和回调有关系。
  • 每当调用目标对象的方法的时候,就会回调该InvocationHandler实例的方法,也就是public Object invoke()方法,我们就可以把限制的条件放在这里,条件符合的时候,就可以调用method.invoke()方法真正的调用目标对象的方法,否则,则可以在这里过滤掉不符合条件的调用。

        五.CGLIB代理

       在这一步中,我们使用一个Enhancer类来创建代理对象,不再使用Proxy。使用Enhancer类,需要为其实例指定一个父类,也就是我们 的目标对象。这样,我们新创建出来的对象就是目标对象的子类,有目标对象的一样。除此之外,还要指定一个回调函数,这个函数就和Proxy的 invoke()类似。

总体来说,使用CGlib的方法和使用Proxy的方法差不多,只是Proxy创建出来的代理对象和目标对象都实现了同一个接口。而CGlib的方法则是直接继承了目标对象。

1.引入jar包

 

2.创建CGLIB实现代理的类

package cn.aop;

import java.lang.reflect.Method;

import cn.service.impl.DoServiceImpl;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * CGLIB实现代理
 * @author hyj
 *
 */
public class CGLIBProxyFactory implements MethodInterceptor {
    //要放回的代理对象
     private Object obj;
     public Object createProxy(Object obj){
         //把传进来的代理对象赋值给obj
         this.obj=obj;
         Enhancer enhancer = new Enhancer();
         //需要为其实例指定一个父类,也就是我们 的目标对象,那么我们新创建出来的对象就是目标对象的子类,有目标对象的一样
         enhancer.setSuperclass(this.obj.getClass());
         //除此之外,还要指定一个回调函数,这个函数就和Proxy的 invoke()类似
         enhancer.setCallback(this);
         return enhancer.create();   

     }
    @Override
    public Object intercept(Object object, Method method, Object[] args,
            MethodProxy methodProxy) throws Throwable {
          Object proxyObject=null;
           DoServiceImpl ds=(DoServiceImpl)obj;
           if(ds.getUserName()!=null){
               proxyObject= methodProxy.invoke(ds, args);
           }else{
               System.out.println("用户名为空,已拦截");
           }
            return proxyObject;
    }

}

测试类 

   

 @Test
   public void CGLIBProxyTest(){
       CGLIBProxyFactory gb=new CGLIBProxyFactory();
       DoServiceImpl ds= (DoServiceImpl)gb.createProxy(new DoServiceImpl("sf"));
       ds.add();
   }

基于Spring AOP的JDK动态代理和CGLIB代理的更多相关文章

  1. 设计模式---JDK动态代理和CGLIB代理

    Cglig代理设计模式 /*测试类*/ package cglibProxy; import org.junit.Test; public class TestCglib { @Test public ...

  2. JDK动态代理和 CGLIB 代理

    JDK动态代理和 CGLIB 代理 JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期期间创建一个接口的实现类来完成对目标对象的代理. 代码示例 接口 public interface ...

  3. JDK动态代理和CGLIB代理的区别

    一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...

  4. 动态代理:JDK动态代理和CGLIB代理的区别

    代理模式:代理类和被代理类实现共同的接口(或继承),代理类中存有指向被代理类的索引,实际执行时通过调用代理类的方法.实际执行的是被代理类的方法. 而AOP,是通过动态代理实现的. 一.简单来说: JD ...

  5. JDK动态代理和cglib代理详解

    JDK动态代理 先做一下简单的描述,通过代理之后返回的对象已并非原类所new出来的对象,而是代理对象.JDK的动态代理是基于接口的,也就是说,被代理类必须实现一个或多个接口.主要原因是JDK的代理原理 ...

  6. JDK动态代理和cglib代理

    写一个简单的测试用例,Pig实现了Shout接口 public class MyInvocation implements InvocationHandler { Object k; public M ...

  7. SpringAOP-JDK 动态代理和 CGLIB 代理

    在 Spring 中 AOP 代理使用 JDK 动态代理和 CGLIB 代理来实现,默认如果目标对象是接口,则使用 JDK 动态代理,否则使用 CGLIB 来生成代理类. 1.JDK 动态代理 那么接 ...

  8. 静态代理、动态代理和cglib代理

    转:https://www.cnblogs.com/cenyu/p/6289209.html 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处 ...

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

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

随机推荐

  1. JS--浏览器兼容之new Date

    Js 中有一个Date属性. 我们可以通过new Date(formatString) 来生命日期. 不过生命日期里面有一个坑就是. new Date('2016-05-13'), Chrome 和 ...

  2. 【原】让H5页面适配移动设备全家 - 前端篇 - PPT

    7月份在部门内给设计中心的同事们带来<让H5页面适配移动设备全家 - 设计师篇 - PPT>的分享,在视觉和交互稿上提出页面适配的建议及提升页面体验的好处,促进前端和设计双方更好的合作,同 ...

  3. 破解 Windows 下Markdown 编辑器 MarkdownPad 2

    MarkdownPad 是 Windows 平台下一款优秀的 Markdown 编辑器,本文简单介绍 Markdown 以及使用一种方法破解 MarkdownPad 使其升级到专业版.该方法仅限于教育 ...

  4. /var/log/messages

    messages 该日志文件是许多进程日志文件的汇总,从该文件可以看出任何入侵企图或成功的入侵,包括整体系统信息,是系统最核心的日志.它包含了系统启动时的引导消息,以及系统运行时的其他状态消息.IO ...

  5. hibernate.cfg.xml常见配置

    转载自:http://blog.csdn.net/qiaqia609/article/details/9456489 <!--标准的XML文件的起始行,version='1.0'表明XML的版本 ...

  6. C#进阶系列——WebApi 路由机制剖析:你准备好了吗?

    前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分. 它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定: ...

  7. 用Tensorflow让神经网络自动创造音乐

    #————————————————————————本文禁止转载,禁止用于各类讲座及ppt中,违者必究————————————————————————# 前几天看到一个有意思的分享,大意是讲如何用Ten ...

  8. ABP模块化

    基于Abp模块化.插件化的设计,开发人员可以将自定义的功能以模块的形式集成到项目中. 模块的加载 模块: 插件: 模块及插件的加载路线: 1. 扩展的HttpApplication对象(在Abp.We ...

  9. 如何利用git由本机向github上传文件

    首先,下载一个git,安装. 安装成功之后,输入以下命令,引号内的为你自己的名字和邮箱git config --global user.name "Your Name"git co ...

  10. maven

    maven常见问题问答 1.前言 Maven,发音是[`meivin],"专家"的意思.它是一个很好的项目管理工具,很早就进入了我的必备工具行列,但是这次为了把project1项目 ...