介绍

AOP是一种概念(思想),并没有设定具体语言的实现。

AOP是对oop的一种补充,不是取而代之。

具体思想:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回到横向业务流。

特征

散布于应用中多处的功能被称为横切关注点

横切关注点可以被描述为影响应用多处的功能

切面提供了取代继承和委托的另一种可选方案

通过声明的方式定义这个功能要以何种方式在何处应用,而无需修改受影响的类

处理过程

核心概念

连接点(join point)

就是程序执行的某个特定的点:

你的一个类里,有15个方法,那就有几十个连接点了

Spring仅支持方法的连接点

连接点就是为了让你好理解切点,搞出来的,明白这个概念就行了

切点(pointcut)

顾名思义切点就是切入哪些连接点,

切点是用来筛选连接点的,来定义都有哪些连接点需要被执行织入通知,

连接点相当于数据库中的记录,而切点相当于查询条件,

一个切点可以匹配出多个连接点

切点指明:都有哪些切点被切面选中了

通知(advice)

切面的工作内容被称为通知,主要是定义我们要做什么事情

比如:我们要记录每一个方法执行前后的时间日志,这个就是我们这个aop的切面工作内容,也就是通知

基于连接点的概念,我们必须要指定这些切点

一般spring的切点都是匹配到方法级别,不会直接定义到某个类某个方法的哪个点,

所以我们需要为这些切点指定在什么时候织入通知。

比如:我们的切点包括了10类的100个方法,那么我们不会为每一个类中的方法单独指定在哪个点(前,后,异常)执行通知,我们会采用统一规则,比如都指定为方法前。

方法前(before)

方法后(after)

方法前后(around)

跑出异常(Exception)

通知指明:做什么事情,在什么时机(统一切入点)执行

切面

通知和切点的结合

通知和切点共同定义了切面的全部内容——它是什么,在何时和何处完成其功能

引入

允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗

织入

织入是把切面应用到目标对象并创建新的代理对象的过程

编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。

类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增

强该目标类的字节码。AspectJ 5的加载时织入(load-time weaving,LTW)就支持以这种方式织入切面。

运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring

AOP就是以这种方式织入切面的。

spring mvc中的Aop的实现方式

基于XML配置的Spring AOP

创建一个普通的pojo类,没有添加任何注解也没有继承和实现任何接口

使用xml的方式创建这个切面处理类的实例

声明切点和切面

注意通知的配置

基于注解配置Spring AOP

首先需要在spring的配置文件中启动对@AspectJ注解的支持

创建一个切面处理类为这个类上加上@Aspect以及@Component注解

创建一个切入点表达式

创建前置通知



@Before

@AfterReturning

@AfterThrowing

@After

@Around

实战

项目中有很多的页面都需要展示用户的信息,

没有使用aop之前每一个controller层都需要去设置用户信息,

于是想起来使用aop的方式解决;

创建一个注解,用于标识哪些conroller处理函数需要添加用户信息

/**
* 注入用户信息
* <p>
* 在controller层中添加这个注解就可以实现在返回页面的
* 的数据里添加上用户的信息
*
* @author WangSen(wangsenhehe@126.com)
* @Date 2018年1月17日
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectionUserInfo {
}

编写切面处理类

/**
* PageService.java
* com.we.core.web.aop
* Copyright (c)
*/ package cn.isuyang.web.www.aop; import java.lang.reflect.Method; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import cn.isuyang.service.UserDetailBaseService;
import cn.isuyang.web.www.annotation.InjectionUserInfo; import com.we.bussiness.sso.interfaces.IFetchUser;
import com.we.core.web.util.AspectUtil;
import com.we.core.web.util.MvcUtil; /**
* 个人中心用户信息切面
*
* @author wangsen(wangsenhehe@126.com)
* @Date 2018年1月17日
*/
@Component
@Aspect
@Order(2)
public class UserInfoAspect {
@Autowired
private UserDetailBaseService userDetailBaseService;
@Autowired
private IFetchUser fetchUser; /**
*
* @param pjp 执行的切点对象
*
* @throws Throwable 方法执行错误的时候会抛此异常
*/
@Around("@annotation(cn.isuyang.web.www.annotation.InjectionUserInfo)")
@Order(1)
public Object setUserInfos(final ProceedingJoinPoint pjp) throws Throwable {
Object result = pjp.proceed();
if (!isNeedSetUserInfo(pjp)) {
return result;
}
MvcUtil.getRequest().setAttribute("userInfo",
userDetailBaseService.getByUserId(fetchUser.getCurrentUserIdWithEx()));
return result;
} /**
* 是否需要设置用户信息
*
* @param pjp 切点
*
* @return true表示存在
*/
private boolean isNeedSetUserInfo(final ProceedingJoinPoint pjp) {
Method method = AspectUtil.getMethod(pjp);
return method.isAnnotationPresent(InjectionUserInfo.class);
}
}

在controller的处理函数上添加 @InjectionUserInfo注解即可

/**
*
* @author WangSen(wangsenhehe@126.com)
* @Date 2017年8月10日
*/
@Controller
@RequestMapping("/personcenter")
public class PersonCenterController {
@Autowired
private PersonCenterViewService personCenterViewService;
/**
* 我的项目
*
* @param model 模型
*/
@RequestMapping
@InjectionUserInfo
public void myProject(final MyProjectListForm listform, @ModelAttribute final Page page, final Model model) {
personCenterViewService.setMyProjectInfo(listform, page, model);
}
/**
* 我的关注
*
* @param model 模型
*/
@RequestMapping
@InjectionUserInfo
public void myFollow(final MyFollowListForm listform, @ModelAttribute final Page page, final Model model) {
personCenterViewService.setMyFollowInfo(listform, page, model);
}
}

资料

aop的基本概念

http://blog.csdn.net/yuanye348623610/article/details/8823429

http://www.jianshu.com/p/601713b20e43

了解知识【AspectJ表达式函数或者叫做切入点表达式】

execution():满足匹配模式字符串的所有目标类方法的连接点

@annotation():任何标注了指定注解的目标方法链接点

资料http://blog.csdn.net/wangpeng047/article/details/8556800

spring aop的实现原理

http://www.cnblogs.com/lcngu/p/5339555.html

http://blog.csdn.net/luanlouis/article/details/51155821

spring aop的简单模拟实现

http://www.cnblogs.com/hqbhonker/p/3822237.html

AOP及spring AOP的使用的更多相关文章

  1. 【AOP】Spring AOP基础 + 实践 完整记录

    Spring AOP的基础概念 ============================================================= AOP(Aspect-Oriented Pr ...

  2. 自己实现 aop 和 spring aop

    上文说到,我们可以在 BeanPostProcessor 中对 bean 的初始化前化做手脚,当时也说了,我完全可以生成一个代理类丢回去. 代理类肯定要为用户做一些事情,不可能像学设计模式的时候创建个 ...

  3. 【Spring AOP】Spring AOP之如何通过注解的方式实现各种通知类型的AOP操作进阶篇(3)

    一.切入点表达式的各种类型 切入点表达式的作用:限制连接点的匹配(满足时对应的aspect方法会被执行) 1)execution:用于匹配方法执行连接点.Spring AOP用户可能最经常使用exec ...

  4. 【Spring AOP】Spring AOP之你必须知道的AOP相关概念(1)

    一.什么是AOP AOP(Aspect-oriented Programming)即面向切面编程,是对OOP( Object-oriented Programming)即面向对象编程的一种补充,AOP ...

  5. 【Spring AOP】Spring AOP的使用方式【Q】

    Spring AOP的三种使用方式 经典AOP使用方式 改进XML配置方式 基于注解的方式 第1种方式可以作为理解spring配置AOP的基础,是最原始的配置方式,也体现了spring处理的过程. 使 ...

  6. AOP和spring AOP学习记录

    AOP基本概念的理解 面向切面AOP主要是在编译期或运行时,对程序进行织入,实现代理, 对原代码毫无侵入性,不破坏主要业务逻辑,减少程序的耦合度. 主要应用范围: 日志记录,性能统计,安全控制,事务处 ...

  7. 死磕Spring之AOP篇 - Spring AOP常见面试题

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  8. 死磕Spring之AOP篇 - Spring AOP总览

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  9. 死磕Spring之AOP篇 - Spring AOP自动代理(一)入口

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

随机推荐

  1. 超详细的 Linux CentOS yum 源的配置与使用【转发+新增】

    一.yum 简介 yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器.起初是由yellow dog 这一发行版的 ...

  2. windows 下使用VMware Workstation Pro 工具,ubuntu创建虚拟机

    本文记录windows 下使用VMware Workstation Pro 工具,ubuntu创建虚拟机 的步骤 第一步 [文件] --- [新建虚拟机]   第二步 弹出的新建虚拟机向导对话框 标准 ...

  3. 【java】打印一个对象即打印出该对象toString()返回值

    public class TestToString { public static void main(String[] args){ Node node1=new Node("东邪&quo ...

  4. Spring框架(三) JDBCTemplate,声明式事务,自动装载(注解)

    JDBCTemplate 按照标准正常项目的结构 结构图: model层 dao层 实现  dao:(DateBase Access Object) 数据访问对象,dao层只用来访问数据库和模型层 s ...

  5. qml demo分析(externaldraganddrop-拖拽)

    一.效果展示 客户端程序拖拽是一个很常见的需求,对于QWidget程序来说,需要重写如图1这么几个方法,通过重写这几个方法的逻辑,我们就可以控制鼠标拖拽的逻辑,糟糕的是QDrag执行exec后是一个阻 ...

  6. Spring MVC框架下的第一个Hello World程序

    本程序是一个maven程序,使用maven方便管理jar包和程序,简化了操作步骤.本程序的目的是通过一个简单的程序,了解Spring MVC框架的基本工作流程,由简入繁的学习Spring MVC框架, ...

  7. ArcGIS API for JavaScript 4.2学习笔记[24] 【IdentifyTask类】的使用(结合IdentifyParameters类)(第七章完结)

    好吧,我都要吐了. 接连三个例子都是类似的套路,使用某个查询参数类的实例,结合对应的Task类,对返回值进行取值.显示. 这个例子是Identify识别,使用了TileLayer这种图层,数据来自Se ...

  8. 修改Linux内核参数提高Nginx服务器并发性能

    当linux下Nginx达到并发数很高,TCP TIME_WAIT套接字数量经常达到两.三万,这样服务器很容易被拖死.事实上,我们可以简单的通过修改Linux内核参数,可以减少Nginx服务器 的TI ...

  9. bat检测文件大小并邮件报警

    rem 获取当前日期 set TimeName=%date:~0,4%%date:~5,2%%date:~8,2% rem 获取文件名 set file=%TimeName%   rem 获取文件大小 ...

  10. Java集合(一) CopyOnWriteArrayList

    CopyOnWriteArrayList 类分析   1. CopyOnWriteArrayList 其中底层实现存放数据是一个Object数组:   private volatile transie ...