AOP是指面向切面编程。

在学习AOP之前先来了解一下代理,因为传说中的AOP其实也对代理的一种应用。

首先来看这样一段代码:

public interface Hello {
void say(String name);
}

实现类:

public class HelloImpl implements Hello {

    public void say(String name) {
System.out.println("Hello!"+name);
}
}

如果现在需要在say调用的前后做一些操作,那最简单的方法就是直接在say方面中增加代码,但这样肯定不够优雅。

这时候可以用第一种代理模式:静态代理

public class HelloProxy implements Hello {

    private Hello hello;

    public HelloProxy(){

        hello=new HelloImpl();

    }

    public void say(String name) {
before();
hello.say(name);
after();
} private void before(){
System.out.println("before");
} private void after(){
System.out.println("after");
}
}

这样我们在保留原来HelloImple中say方法的同时,用HelloProxy代理在say方法的前后增加了before和after

调用一下试试:

 public static void main(String[] args){
Hello helloProxy=new HelloProxy();
helloProxy.say("Gary");

运行结果:

那么新的问题来了,如果每次都需要写一个代理类不也很麻烦吗,项目中就会有很多个xxxProxy,因此就出现了 JDK动态代理

代码如下:

public class DynamicProxy implements InvocationHandler {

    private Object target;

    public DynamicProxy(Object target){
this.target=target;
} public <T> T getProxy(){
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
} public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result=method.invoke(target,args);
after();
return result;
} private void before(){
System.out.println("before");
} private void after(){
System.out.println("after");
}
}

注:Proxy.newProxyInstance()参数有三个:

  • ClassLoader
  • 该实现类的所有接口
  • 动态代理对象

在该类中target就是被代理的对象,该类实现了InvocationHandler接口,通过反射去动态创建Hello接口的代理类

那么现在的调用就变简单了:

 public static void main(String[] args){
DynamicProxy dynamicProxy=new DynamicProxy(new HelloImpl());
Hello helloProxy= dynamicProxy.getProxy();
helloProxy.say("gary");
}

用了JDK动态代理后,我们觉得还是有问题,如果要代理一个没有接口的类,该怎么办呢,于是就轮到我们的 CGlib动态代理 出场了。

在Spring、Hibernate等框架中都用到了CGlib动态代理,maven资源如下:

 <!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.6</version>
</dependency>

他的使用需要实现MethodInterceptor类,并完成intercept方法。CGlib 提供的是方法级别的代理:

public class CGLibProxy implements MethodInterceptor {

    public <T> T getProxy(Class<T> cls){
return (T) Enhancer.create(cls,this);
} public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object result=methodProxy.invokeSuper(o,objects);
after();
return result;
} private void before(){
System.out.println("before");
} private void after(){
System.out.println("after");
}
}

这样使用时就不需要提供接口了:

  public static void main(String[] args){
CGLibProxy cgLibProxy= new CGLibProxy();
Hello hello=cgLibProxy.getProxy(HelloImpl.class);
hello.say("Gary");
}

最后再改造一下,加上单例模式就更完美了

    private static CGLibProxy instance=new CGLibProxy();

    private CGLibProxy(){
}
public static CGLibProxy getInstance(){
return instance;
}

调用就改为:

public static void main(String[] args){
Hello hello=CGLibProxy.getInstance().getProxy(HelloImpl.class);
hello.say("Gary");
}

springAOP之代理的更多相关文章

  1. springAOP之代理模式

    springAOP指的是在spring中的AOP,什么是AOP,相对于java中的面向对象(oop),在面向对象中一些公共的行为,像日志记录,权限验证等如果都使用面向对象来做,会在每个业务方法中都写上 ...

  2. 深入理解SpringAOP之代理对象

    本篇文章主要带大家简单分析一下AOP的代理对象,至于AOP是什么,如何配置等基础性知识,不在这里讨论.阅读前请先参考:代理模式,在这之前我们需要了解springframework的三个核心接口与get ...

  3. Spring知识点总结(四)之SpringAOP基础 - 代理设计模式

        1. 分析程序中存在的问题(高内聚,低耦合)        通过springIOC DI) 以及注解的使用,成功解决了在程序中层与层之间出现的耦合的问题,但是在很多地方仍然存在非该层应该实现的 ...

  4. spring-AOP动态代理,以及aspectJ的xml配置或注解配置方法,各个拦截器的使用顺序

    package com.itheima.aspect; public class MyAspect { public void check_Permissions(){ System.out.prin ...

  5. Spring-AOP动态代理技术(底层代码)

    1.JDK代理:基于接口的动态代理技术 目标对象必须有接口,目标对象有什么方法,目标接口就有什么方法, 运行期间基于接口动态生成代理对象,所以代理对象也就有目标对象同样的方法. 注意:以下代码只是底层 ...

  6. SpringAOP和AspectJ

    SpringAOP和AspectJ的关系 问题:之前对 SpringAOP和AspectJ的关系感到疑惑,因为曾经在书上看过SpringAOP集成了AspectJ,那么SpringAOP是直接使用了A ...

  7. 完整剖析SpringAOP的自调用

    摘要 spring全家桶帮助java web开发者节省了很多开发量,提升了效率.但是因为屏蔽了很多细节,导致很多开发者只知其然,不知其所以然,本文就是分析下使用spring的一些注解,不能够自调用的问 ...

  8. Spring源码系列(三)--spring-aop的基础组件、架构和使用

    简介 前面已经讲完 spring-bean( 详见Spring ),这篇博客开始攻克 Spring 的另一个重要模块--spring-aop. spring-aop 可以实现动态代理(底层是使用 JD ...

  9. Spring框架系列(12) - Spring AOP实现原理详解之JDK代理实现

    上文我们学习了SpringAOP Cglib动态代理的实现,本文主要是SpringAOP JDK动态代理的案例和实现部分.@pdai Spring框架系列(12) - Spring AOP实现原理详解 ...

随机推荐

  1. iOS中 UIMPMediaPickerController播放系统音乐

    布局如下: 引入框架: #import <AVFoundation/AVFoundation.h> #import <MediaPlayer/MediaPlayer.h> 遵循 ...

  2. Java线程的状态

    Java线程的状态 线程对象在不同的运行时期有不同的状态,状态信息就存在于Thread中的State枚举中,如下所示: public enum State { /** * 至今尚未启动的线程处于这种状 ...

  3. iOS中 数据持久化 UI高级_17

    数据持久化的本质就是把数据由内写到本地(硬盘中),在iOS指将数据写到沙盒文件夹下: 沙盒机制:指的就是采用沙盒文件夹的形式管理应用程序的本地文件,而且沙盒文件夹的名字是随机分配的,采用十六进制方法命 ...

  4. Socket层实现系列 — 信号驱动的异步等待

    主要内容:Socket的异步通知机制. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 概述 socket上定义了几个IO事件:状态改变事件.有数据可读事 ...

  5. 【一天一道LeetCode】索引目录 ---C++实现

    [一天一道LeetCode]汇总目录 这篇博客主要收藏了博主所做题目的索引目录,帮助各位读者更加快捷的跳转到对应题目 目录按照难易程度:easy,medium,hard来划分,读者可以按照难易程度进行 ...

  6. Java中Set的contains()方法

    Java中Set的contains()方法 -- hashCode与equals方法的约定及重写原则 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashCode() a ...

  7. Android Studio 1.2.2设置显示行号

    Android Studio设置显示行号的方法与Eclipse有少许差别,直接在代码中右键,弹出右键菜单是没有显示行号功能的. 在Android Studio中设置方法有二: 1.临时显示行号 在单个 ...

  8. 【一天一道LeetCode】#4 Median of Two Sorted Arrays

    一天一道LeetCode (一)题目 There are two sorted arrays nums1 and nums2 of size m and n respectively. Find th ...

  9. Java的依赖注入(控制反转)

    两个主角"依赖注入"和"控制反转": 1.二都说的都是同一件事,只是叫法不同.是一个重要的面向对象编程的法则,也是一种设计模式: 2.英文原称:依赖注入,Dep ...

  10. AndFix使用感想

    AndFix已经使用了一段时间了,但是到AndFix上看了一下,最近2个月都没有更新代码了,有141个issues和3个pull request没人处理,其实AndFix的Contributors就俩 ...