什么是AOP?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面

面向切面编程(aop)是对面向对象编程(oop)的补充,
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。

aop框架具有的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性
前提:要实现AOP的模拟就要知道动态代理,Spring中使用了两种动态代理方式,一种是基于JDK的动态代理,一种是基于CGlib的动态代理。为什么会有两种,那是因为JDK的动态代理只能是

针对接口。

先看下面的代码dao层
Java代码     
package com.lbx.dao;   
import com.lbx.model.User;   
public interface UserDAO {   
     public void save(User user);   
     //public void delete();   

dao实现层
Java代码     
package com.lbx.dao.impl;

import com.lbx.dao.UserDAO;   
import com.lbx.model.User;   
   
public class UserDAOImpl implements UserDAO {   
   
     @Override  
     public void save(User user) {   
            
         System.out.println("a user saved!!!");   
   
     }   
      
     /*public void delete(){  
         System.out.println("UserDAOImpl.delete()");  
     }  
*/  

现在我们要在User的save之前和之后做一些处理(拦截器),我们先看一种最简单的方法(在类中加代码)
Java代码     
package com.lbx.dao.impl;   
 
import com.lbx.dao.UserDAO;   
import com.lbx.model.User;   
  
public class UserDAOImpl1 implements UserDAO {   
  
    @Override  
    public void save(User user) {   
            
         System.out.println("method start....");   
            
         System.out.println("a user saved!!!");   
            
         System.out.println("method stoped...");   
   
     }   
   

显然,这是可以的,但是这样明显就不好,第一代码没可重用性,第二这是在知道源码的情况下,现实中我们有很多情况都不知道源码,在这种情况下,明显这方式就不行了。下面就是第二

种解决方案:
Java代码     
package com.lbx.dao.impl;   
import com.lbx.model.User;
  
public class UserDAOImpl2 extends UserDAOImpl{   
   
     public void save(User user) {   
           
         System.out.println("method start....");   
         super.save(user);   
         System.out.println("method stoped.....");   
            
     }   
   

先让一个类实现了那个接口,然后要用的类继承那个实现类,这样也可以达到目的(其实这就是一种“组合模式”),这种方式在一定的程度上是利用的资源,代码的重用性。但是还是不好

,当我们要做很多的处理的时候,这样我们就要组合和多的类,明显就不好。下面是第三种:使用动态代理。                       先看处理方法(拦截器)
Java代码     
package com.lbx.interceptor;   
public class UserInterceptor {   
    //第一个拦截方法   
     public void method1(){   
         System.out.println("UserInterceptor.method1()");   
     }   
        
     //第二个拦截方法   
     public void method2(){   
         System.out.println("UserInterceptor.method2()");   
     }   
        

产生代理的类,实现InvocationHandler接口
Java代码     
package com.lbx.interceptor;   
import java.lang.reflect.InvocationHandler;   
import java.lang.reflect.Method;   
public class ProxyHandler implements InvocationHandler {   
        
     //创建需要代理的目标对象   
    private Object targer;   
     //创建拦截器的实例   
     UserInterceptor u = new UserInterceptor();   
        
     public Object invoke(Object proxy, Method method, Object[] args)   
             throws Throwable {   
         Object result = null;   
   
         //if(method.getName().equals("save")){   
             u.method1();   
             result = method.invoke(targer, args);   
             u.method2();   
         //}else{   
             //result = method.invoke(targer, args);   
         //}   
            
         return result;   
     }   
        
     //用于设置传人目标对象的方法   
     public void setTarger(Object o){   
         this.targer = o;   
     }


获得代理的实例类
Java代码     
package com.lbx.interceptor;   
import java.lang.reflect.Proxy;   
import com.lbx.dao.impl.UserDAOImpl;   
public class UserProxyFactory {   
  
     public static Object getProxy(Object object){   
         ProxyHandler p = new ProxyHandler();   
         p.setTarger(object);   
         return Proxy.newProxyInstance(UserDAOImpl.class.getClassLoader(), object.getClass().getInterfaces(), p);  
     }    

服务层使用动态代理
Java代码     
package com.lbx.service;   
   
import com.lbx.dao.UserDAO;   
import com.lbx.dao.impl.UserDAOImpl;   
import com.lbx.interceptor.UserProxyFactory;   
import com.lbx.model.User;   
  
public class UserService {   
       
     //private UserDAO userDAO = new UserDAOImpl1();   //第一种就是写死,直接在方法里写   
     //private UserDAO userDAO = new UserDAOImpl2();     //第二种就是通过继承来实现(方法执行前后加一些业务逻辑)  
     //private UserDAO userDAO = new UserDAOImpl3();       //第三种是通过组合来完成的   
     UserDAO userDAO = new UserDAOImpl();   
     UserDAO u = null;   
        
     Object object = UserProxyFactory.getProxy(userDAO);   
        
     /*public UserDAO getUserDAO() {  
         return userDAO;  
     }  
  
     public void setUserDAO(UserDAO userDAO) {  
         this.userDAO = userDAO;  
     }*/  
   
     /*public void add(User user){  
         this.userDAO.save(user);  
     }*/  
        
     public void add(User user){   
         if(object instanceof UserDAO){   
             u = (UserDAO)object;   
         }   
         u.save(user);   
         //u.delete();   
     }  
}

Spring中AOP的模拟实现的更多相关文章

  1. Spring中AOP相关的API及源码解析

    Spring中AOP相关的API及源码解析 本系列文章: 读源码,我们可以从第一行读起 你知道Spring是怎么解析配置类的吗? 配置类为什么要添加@Configuration注解? 谈谈Spring ...

  2. Spring中AOP原理,源码学习笔记

    一.AOP(面向切面编程):通过预编译和运行期动态代理的方式在不改变代码的情况下给程序动态的添加一些功能.利用AOP可以对应用程序的各个部分进行隔离,在Spring中AOP主要用来分离业务逻辑和系统级 ...

  3. Spring中AOP简介与切面编程的使用

    Spring中AOP简介与使用 什么是AOP? Aspect Oriented Programming(AOP),多译作 "面向切面编程",也就是说,对一段程序,从侧面插入,进行操 ...

  4. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

  5. Spring 中aop切面注解实现

    spring中aop的注解实现方式简单实例   上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了. 注解方式实现aop我们 ...

  6. Spring中AOP相关源码解析

    前言 在Spring中AOP是我们使用的非常频繁的一个特性.通过AOP我们可以补足一些面向对象编程中不足或难以实现的部分. AOP 前置理论 首先在学习源码之前我们需要了解关于AOP的相关概念如切点切 ...

  7. AOP 与 Spring中AOP使用(上)

    AOP简介 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP是OOP的延续 ...

  8. JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解

    在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...

  9. 浅析Spring中AOP的实现原理——动态代理

    一.前言   最近在复习Spring的相关内容,刚刚大致研究了一下Spring中,AOP的实现原理.这篇博客就来简单地聊一聊Spring的AOP是如何实现的,并通过一个简单的测试用例来验证一下.废话不 ...

随机推荐

  1. Linux下tomcat管理查看控制台|杀死tomcat进程

    查看控制台 # tail -f catalina.out 脚本执行权限chmod u+x *.sh #看是否已经有tomcat在运行了 ps -ef |grep tomcat #如果有,用kill; ...

  2. 删除sql server中重复的数据

    原文:删除sql server中重复的数据 with list_numbers as( select Name, AuthorOrTime, Url, Price, EstimatePrice, Si ...

  3. 读书笔记—CLR via C#同步构造28-29章节

    前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...

  4. 喜大本\\ u0026普,微软的开源

    词汇表--喜大本\\ u0026普:爱过.有趣的游戏,庆祝.奔走相告.简而言之<reload=1">微软宣布.NET开发环境开源>是个好消息. 前言及历史回想 就我个人来说 ...

  5. JavaScript闭包小窥

    众所周知,JavaScript没有块级作用域,只有函数作用域.那就意味着定义在函数中的参数和变量在函数外部是不可见的,而在一个函数内部任何位置定义的变量,在该函数内部任何地方都可见.这带来的好处是内部 ...

  6. Java 8新特性前瞻

    快端午小长假了,要上线的项目差不多完结了,终于有时间可以坐下来写篇博客了. 这是篇对我看到的java 8新特性的一些总结,也是自己学习过程的总结. 几乎可以说java 8是目前为止,自2004年jav ...

  7. 解决Xcode升级7.0后,部分.a静态库在iOS9.0的模拟器上,link失败的问题

    简单描述一下这个问题:我们项目中使用了Google大神开发的LevelDB键值对数据库,在Xcode6,iOS8的环境下,编译好的.a静态库是可以正常使用的.但是升级后,发现在模拟器上无法link成功 ...

  8. Hadoop集成

    Hadoop集成   长期以来,我每开个系列,只有兴趣写一篇,很难持之与恒.为了克服这个长久以来的性格弱点,以及梳理工作半年的积累.最近一个月会写两篇关于Mongo在地理大数据方面的实践和应用,一篇关 ...

  9. Linux环境进程间通信(二):信号(下)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  10. SQLSERVER数据库自动备份工具SQLBackupAndFTP(功能全面)

    挺好用的SQLSERVER数据库自动备份工具SQLBackupAndFTP(功能全面) 这个工具主要就是自动备份数据库,一键还原数据库,发送备份数据库日志报告到邮箱,自动压缩备份好的数据库 定期执行数 ...