基础篇——代理模式之SpringAOP

一、AOP概述

  AOP思想的实现一般都是基于代理模式,JDK动态代理模式只能代理接口,而不能代理类。但是SpringAOP同时支持CGLIB、JDK、ASPECTJ这三种代理模式,因此,如果目标的对象实现了接口,SpringAOP将会采用JDK动态代理,如果目标对象没有实现接口,SpringAOP切换成CGLIB动态代理。

在实际情况下,我们通常需要对一个接口实现多个切面,比如日志打印、分布式锁、权限校验等等。这时候我们就会面临一个优先级的问题,这么多的切面如何告知Spring执行顺序呢?这就需要我们定义每个切面的优先级,我们可以使用注解@Order(i)来表示切面的优先级,i的值越小,优先级越高。假设我们现在一共有两个切面,一个日志处理切面,设置其@Order(100);一个分布式锁,设置其@Order(99),那么分布式锁的优先级是高于日志处理的,对于通知@Before来说,先执行分布式锁,再执行日志处理;对于通知@After和@AfterReturning来说,先执行日志处理,再执行分布式锁,这样就可以完成一个首尾的对应,也可以理解为先进后出原则。

二、静态代理

  接口类:

interface Person { void speak();}

  实体类:

class Actor implements Person {
     private String content;
     public Actor(String content) { this.content = content;}
     public void speak(){
        System.out.println(this.content);
      }
     }

  代理类:

class Agent implements Person {
        private Actor actor;
        private String before;
        private String after;
        public Agent(Actor actor, String before, String after){
            this.actor = actor;
            this.before = before;
            this.after = after;
         }
          public void speak(){
            System.out.println("前置通知:" + this.before);
            this.actor.speak();
            System.out.println("后置通知:" + this.after);
         }
     }

  测试类:

public class StaticProxyTest{
            public static void main(String[] args){
                Actor actor = new Actor("实体类的真正内容");
                Agent agent = new Agent(actor, "前置内容", "后置内容");
                agent.speak();
             }
         }

二、动态代理

  1、JDK自带动态代理

最核心的一个接口和方法,java.lang.reflect包下的InvocationHandler接口:

public interface InvocationHandler{
              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
         }

proxy:被代理的类的实例

method:调用被代理的类的方法

args:该方法需要的参数

我们实现该接口,在invoke方法中调用实体类的方法,并在其前后进行动态操作,从而实现动态代理。另外一个很重要的静态方法是java.lang.reflect包中的Proxy类的newProxyInstance方法:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException;

    loader:被代理类的类加载器

interfaces:被代理类的接口数组

h:调用处理器类的对象实例

该方法会返回一个被修改过的类的实例,从而可以自由的调用该实例的方法。

  Person接口:

public interface Person{
                 public void show();
             }

  Actor实体类:

public class Actor implements Person{
              public void show(){
                   System.out.println("真正实现的方法");
             }
         }

  Agent代理类:

public class DynamicAgent{
              static class Agent implements InvocationHandler{
                private Object proxy;
                public Agent(Object proxy){
                     this.proxy = proxy;
                }

                public Object invoke(Object object, Method method, Object[] args) throws Throwable {
                    System.out.println("自己添加的前置通知");
                   //真正调用的方法
                   Object res = method.invoke(this.proxy, args);
                   System.out.println("自己添加的后置通知");
                   return res;
                 }
              public static Object agent(Class interfaceClazz, Object proxy){
                   return Proxy.newProxyInstance(interfaceClazz.getClassLoader(), new Class[]{interfaceClazz}, new Agent(proxy));
             }
            }
         }

  测试类ReflectTest:

public class ReflectTest{
              public static void main(String[] args) throws InvocationTargetException, IllegralAccessException {
                 Person person = (Person)DynamicAgent.agent(Person.class, new Actor());
                 person.show();
             }
         }

  这样以后对于不同的实现类来说,可以用同一个动态代理类来进行代理,但是这种方法有个缺点,就是被代理的类一定要是实现了某个接口的。

  2、CGLIB动态代理

同样的CGLIB也有两个重要的方法,在MethodInterceptor接口中的getInstance(Object proxy)和intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)方法 。

  CGLIB代理类CglibAgent:

public class CglibAgent implements MethodInterceptor {
            private Object proxy;
             public Object getInstance(Object proxy){
                this.proxy = proxy;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(this.proxy.getClass);
                enhancer.setCallback(this);
                return enhancer.create();
             }
             public Object intercept(Object o, Method method, Object[] object, MethodProxy methodProxy) throws Throwable{
                System.out.println("自己添加的前置通知");
                Object res = methodProxy.invokeSuper(this.proxy, args);
                System.out.println("自己添加的后置通知");
                return res;
             }
              //测试
              public static void main(String[] args){
                     CglibAgent cglibAgent = new CglibAgent();
                     Actor actor = (Actor)cglibAgent.getInstance(new Actor());
                     actor.show();
             }
         }

  使用CGLIB处理之后,可以直接对实体类进行动态代理。

原文地址:https://www.cnblogs.com/zzb-yp/p/12625277.html

时间: 2024-10-11 00:31:32

基础篇——代理模式之SpringAOP的相关文章

设计模式之代理模式(Proxy Pattern)_远程代理解析

一.什么是代理模式? 顾名思义,代理就是第三方,比如明星的经纪人,明星的事务都交给经纪人来处理,明星只要告诉经纪人去做什么,经纪人自然会想办法去做,做完之后再把结果告诉明星就好了 本来是调用者与被调用者之间的直接交互,现在把调用者与被调用者分离开,由代理负责传递信息来完成调用 二.代理模式有什么用? 代理模式是一个很大的模式,所以应用很广泛,从代理的种类就能看出来了: 远程代理:最经典的代理模式之一,远程代理负责与远程JVM通信,以实现本地调用者与远程被调用者之间的正常交互 虚拟代理:用来代替巨

iOS开发-代理模式

代理模式有的时候也被称之为委托模式,但是实际上两者是有分别的,代理模式为另一个对象提供一个替身或占位符访问这个对象,代理对象和控制访问对象属于同一类,委托对象和对象不一定属于同一类.两者都可以控制类的访问,访问代理的方法A也就意味着访问对象的方法A,访问委托对象方法A执行的是可以是对象的方法B.从实际开发的角度看,委托属于代理模式的扩大版,并没有那么多的限制. 基础知识 代理模式相对比较简单,可以简单的看一下UML类图: 代理模式以便管理客户对对象的访问,管理访问的方式有很多种.远程代理管理客户

Spring学习五、Java配置Spring与代理模式

九.使用Java的方式配置Spring JavaConfig是Spring的一个子项目,在Spring4之后,成为了核心功能 @Configuration public class MyConfig { @Bean public User getUser() { return new User(); } } 纯Java配置,在SpringBoot中随处可见 十.代理模式 代理模式是SpringAOP的底层! 代理模式的分类 静态分类 动态代理 10.1 静态代理 角色分析: 抽象角色:一般会使用

OC学习篇之---代理模式

在前一篇文章我们介绍了OC中的协议的概念:http://blog.csdn.net/jiangwei0910410003/article/details/41776015,这篇文章我们就来介绍一下OC中的代理模式,关于代理模式,如果还有同学不太清楚的话,就自己去补充知识了,这里就不做介绍了,这里只介绍OC中是如何实现代理模式的. 这里举一个简单的例子: 小孩类,护士类,保姆类,其中小孩类有两个方法:wash和play 这里代理对象就是:护士类.保姆类,小孩类是被代理对象. 看一下代码: 首先看一

设计模式总结篇系列:代理模式(Proxy)

时代在发展,我们发现,现在不少明星都开始进行微访谈之类的,有越来越多的参与捐赠等.新的一天开始了,首先看下新的一天的日程安排: 1 interface Schedule{ 2 3 public void weiTalk(); 4 5 public void donation(); 6 7 } Schedule接口定义了今天的形成安排,主要包括微访谈和捐款.那么看一下实现此接口的明星类定义: 1 class Star implements Schedule { 2 3 @Override 4 pu

设计模式之代理模式(Proxy Pattern)_补充篇

写在前面: 代理模式的内部原理,作用及远程代理的实现在上一篇博文中都做了详细解释,本文只是对其内容的补充,介绍其它代理 一.虚拟代理 首先,明确虚拟代理的作用:在巨大对象被真正创建出来之前,用虚拟代理来代替巨大对象(保证了巨大对象在需要的时候才被创建,避免资源浪费) 虚拟代理我们可能经常在用,只是不认识它而已,比如: 我们的程序中可能存在密集的计算或者从服务器取得大量数据这样耗时耗资源的操作,一般都会先显示默认信息,或者显示动画表示我们的程序还在努力工作,在操作完成之后显示获得的信息 其中就用到

(转载)OC学习篇之---代理模式

在前一篇文章我们介绍了OC中的协议的概念,这篇文章我们就来介绍一下OC中的代理模式,关于代理模式,如果还有同学不太清楚的话,就自己去补充知识了,这里就不做介绍了,这里只介绍OC中是如何实现代理模式的. 这里举一个简单的例子: 小孩类,护士类,保姆类,其中小孩类有两个方法:wash和play 这里代理对象就是:护士类.保姆类,小孩类是被代理对象. 看一下代码: 首先看一下小孩类: Children.h 1 // 2 // Children.h 3 // 12_DesignStyle 4 // 5

责任链模式综述(基础篇)

摘要: 本篇综述责任链模式的提出动机.原理结构.典型实现和应用场景,并结合具体实例展现了其灵活性.可插拔性和松耦合性.首先,结合我们日常生活中"打扑克"的例子引出了责任链模式产生动机,并揭示了其应用场景.紧接着,我们概述了责任链模式的内涵和结构,即通过建立一条责任链来组织请求的处理者,请求将沿着链进行传递,而请求发送者无须知道请求在何时.何处以及如何被处理,实现了请求发送者与处理者的解耦.此外,本文给出了责任链模式的典型实现和并结合具体实例介绍其使用方式,以便我们更好体会其优点. 版权

代理模式第一篇

简单的说就是有一个远程服务和若干台监视器,监视器用来监视远程服务中的有关数据.监视任务的 障碍点在于远程服务和监视器程序不在同一个JVM上.这就导致监视器没法在本地直接调用服务器的 方法对其进行监控.我们需要一个代理来,监视器所做的就像是在做远程方法调用,但其实只是调用 本地堆中的"代理"对象上的方法,再由代理处理所有网络通信的低层细节. 制作远程服务的步骤: 1:制作远程接口,接口定义了要供客户调用的远程方法. MyRemote.java : interface MyRemote e