什么是AOP?
基本概念
切面(aspect):横切关注点被模块化的特殊对象。
通知(advice):切面必须要完成的工作。切面中的每个方向称之为通知。通知是在切面对象中的。
目标(target):被通知的对象。
代理(proxy):向目标对象应用通知后创建的对象。

连接点(joinpoint):目标对象的程序执行的某个特定位置。如某个方向调用前,调用后的位置。包括两个信息:1.目标程序的哪个方法?2.方法执行前还是执行后?
切点(pointcut):每个类会有多个连接点,AOP通过切点定位到特定的边接点。
类比,连接点相当于数所成方圆 中的记录,而切点相当于查询条件。一个切点匹配多个连接点。

一、注解(Annotation)方式实现Spring面向切面

  首先定义一个接口(为了不违反开闭原则和更好的可扩展性,目标对象实际上是实现了已定义好的某个接口)

package com.entities;

public interface IHuman {
public void eat();
public void sleep();
}

  创建一个继承自IHuman接口的类

  为该类加上@Compoent注解

package com.entities;

import org.springframework.stereotype.Component;

@Component
public class Chinese implements IHuman { @Override
public void eat() {
System.out.println("中国人在吃饭");
//int i =1/0;
} @Override
public void sleep() {
System.out.println("中国人在睡觉"); } }

  定义一个切面类

  为该类加上@Aspect注解@Compoent注解

package com.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; @Aspect
@Component
public class HumanAOP {
@Before("execution(* com.entities.*.eat(..))")//before是在方法执行之前
public void beforeeat(){
System.out.println("先洗 手");
}
@After(value = "execution(* com.entities.*.eat(..))")//after是在方法执行之后
public void aftereat(){
System.out.println("去漱口");
}
@AfterThrowing(value="execution(* com.entities.*.eat(..))",throwing="ex")//AfterThrowing是在方法报错抛异常时执行
public void except(Exception ex){
System.out.println(ex.getMessage());
System.out.println("撑死了");
}
@AfterReturning(value="execution(* com.entities.*.eat(..))",returning="result")//AfterReturning在目标方法执行成功后执行的通知
public void fanhui(Object result){
System.out.println(result);
System.out.println("吃完了");
}
@Before("execution(* com.entities.*.sleep(..))")
public void beforesleesp(){
System.out.println("先洗澡");
}
}

  创建xml文件

  <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>自动为匹配的类生成代理对象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 自动扫描包下的类,并将其实例化。多个包之间用,隔开 -->
<context:component-scan base-package="com.entities,com.aop"></context:component-scan>
<!-- 配置文件中启动AspectJ的注解功能 ,默认是false,要将其改为true -->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>

  定义一个main函数类进行效果实现

package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.entities.Chinese; public class Test { public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Chinese c= context.getBean(Chinese.class);
c.eat();
c.sleep(); } }
先洗 手
中国人在吃饭
去漱口
null
吃完了
先洗澡
中国人在睡觉

二、XML方式实现Spring面向切面

  同理,先定义一个接口

package com.entities;

public interface IHuman {
public void eat();
public void sleep();
}

  创建一个继承自IHuman接口的类

package com.entities;

public class Chinese implements IHuman {

    @Override
public void eat() {
System.out.println("中国人在吃饭");
//int i =1/0;
} @Override
public void sleep() {
System.out.println("中国人在睡觉"); } }

  定义一个切面类

package com.aop;

public class HumanAOP {

    public void beforeeat(){
System.out.println("先洗 手");
} public void aftereat(){
System.out.println("去漱口");
} public void except(Exception ex){
System.out.println(ex.getMessage());
System.out.println("撑死了");
} public void fanhui(Object result){
System.out.println(result);
System.out.println("吃完了");
} public void beforesleesp(){
System.out.println("先洗澡");
}
}

  创建xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd"
default-autowire="byName"
> <bean id="chinese" class="com.entities.Chinese"></bean>
<bean id="gou" class="com.entities.Gou"></bean>
<bean id="humanaop" class="com.aop.HumanAOP"></bean> <aop:config>
<aop:pointcut expression="execution(* com.entities.*.eat())" id="aftereat"/>
<aop:pointcut expression="execution(* com.entities.*.eat())" id="beforeeat"/> <aop:aspect ref="humanaop">
<aop:after method="aftereat()" pointcut-ref="aftereat"/>
<aop:before method="beforeeat()" pointcut-ref="beforeeat"/>
</aop:aspect>
</aop:config> </beans>

  定义一个main函数来执行

package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.entities.Chinese;
import com.entities.IHuman; public class Test { public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
IHuman c= (IHuman)context.getBean("chinese");
c.eat(); } }
先洗 手
中国人在吃饭
去漱口

通知分类:
前置通知(@Before) -- 在目标方法执行前执行的通知。
后置通知(@After) -- 在目标方法执行后执行的通知。无论是否发生异常。后置通知中,无法读取目标方法返回的结果。
返回通知(@AfterReturnning) --在目标方法执行成功后执行的通知。在返回通知中可以访问目标返回结果的。
@AfterReturnning(value="execution(* com.itnba..*(..))",returning="result")
public void afterRun(Object result){
System.out.println(result);
}

异常通知(@AfterThrowing) -- 在目标方法执行出错后执行的通知。
@AfterThrowing(value="execution(* com.itnba..*(..))",throwing="ex")
public void afterThrowing(Exception ex){
System.out.println(ex.getMessage());
}

环绕通知(@Around) -- 需要切面方法携带ProceedingJoinPoion参数,类似于一个完整的动态代理,环绕通知必须要有一个返回值,是目标方法的返回值。

@Around("execution(* com.itnba..*(..))")
public object aroundAdvice( ProceedingJoinPoint pjp){ object obj = null;
try{
//做前置通知
obj = pjp.proceed();
//做返回通知
}
catch(Exception ex){
//做异常通知
}
//做后置通知
return obj;
}

添加日志:

切面方法可以加入参数(JoinPoint) joinPost.getSignature().getXXX()获得相关方法信息
切面方法中可以加入Object参数,用来获得目标方法的返回值(只对返回通知起作用)

Spring AOP(面向切面)的更多相关文章

  1. 详细解读 Spring AOP 面向切面编程(二)

    本文是<详细解读 Spring AOP 面向切面编程(一)>的续集. 在上篇中,我们从写死代码,到使用代理:从编程式 Spring AOP 到声明式 Spring AOP.一切都朝着简单实 ...

  2. 浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

    简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring ...

  3. spring AOP面向切面编程学习笔记

    一.面向切面编程简介: 在调用某些类的方法时,要在方法执行前或后进行预处理或后处理:预处理或后处理的操作被封装在另一个类中.如图中,UserService类在执行addUser()或updateUse ...

  4. 【spring-boot】spring aop 面向切面编程初接触--切点表达式

    众所周知,spring最核心的两个功能是aop和ioc,即面向切面,控制反转.这里我们探讨一下如何使用spring aop. 1.何为aop aop全称Aspect Oriented Programm ...

  5. 【spring-boot】spring aop 面向切面编程初接触

    众所周知,spring最核心的两个功能是aop和ioc,即面向切面,控制反转.这里我们探讨一下如何使用spring aop. 1.何为aop aop全称Aspect Oriented Programm ...

  6. 【Spring系列】Spring AOP面向切面编程

    前言 接上一篇文章,在上午中使用了切面做防重复控制,本文着重介绍切面AOP. 在开发中,有一些功能行为是通用的,比如.日志管理.安全和事务,它们有一个共同点就是分布于应用中的多处,这种功能被称为横切关 ...

  7. 从源码入手,一文带你读懂Spring AOP面向切面编程

    之前<零基础带你看Spring源码--IOC控制反转>详细讲了Spring容器的初始化和加载的原理,后面<你真的完全了解Java动态代理吗?看这篇就够了>介绍了下JDK的动态代 ...

  8. Spring AOP面向切面编程详解

    前言 AOP即面向切面编程,是一种编程思想,OOP的延续.在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等等.在阅读本文前希望您已经对Spring有一定的了解 注:在能对代码进行添 ...

  9. Spring AOP 面向切面编程相关注解

    Aspect Oriented Programming 面向切面编程   在Spring中使用这些面向切面相关的注解可以结合使用aspectJ,aspectJ是专门搞动态代理技术的,所以比较专业.   ...

随机推荐

  1. 洛谷 P1426 小鱼会有危险吗

    题目描述 有一次,小鱼要从A处沿直线往右边游,小鱼第一秒可以游7米,从第二秒开始每秒游的距离只有前一秒的98%.有个极其邪恶的猎人在距离A处右边s米的地方,安装了一个隐蔽的探测器,探测器左右x米之内是 ...

  2. ZOJ 1729 Hidden Password (字符串最小表示)

    以前听过,不知道是什么,其实就是字符串首尾相连成一个环,n种切法求一个字典序最小的表示. 朴素算法大家都懂.O(n)的算法代码非常简单,最主要的思想是失配的时候尽可能大的移动指针. 另外附上一个不错的 ...

  3. [论文理解] MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications

    MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications Intro MobileNet 我 ...

  4. 如何使用Python生成200个优惠券(激活码)

    解析: 常见的优惠券(激活码)是由数字.字母(大小写)组成: string.ascii_letters   26个大小写字母: string.digits 0-9数字: 随机组合 使用random.s ...

  5. Robot Framework(一)入门

    1.1简介 Robot Framework是一个基于Python的,可扩展的关键字驱动的测试自动化框架,用于端到端验收测试和验收测试驱动开发(ATDD).它可用于测试分布式异构应用程序,其中验证需要涉 ...

  6. centos7-httpd服务器

    Apache WEB服务器入门简介: Apache HTTP Server是Apache软件基金会的一个开源的网页服务器,可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是目 ...

  7. 安装python3.6 pip3 flake8

    apt-get install python3-pip # Python3 ➜  ~ pip3 -V                                             pip 9 ...

  8. echarts实现仪表盘(自己动起来,没有后端,顺便重温math.random

    let a = parseInt(Math.random() * (2 + 1), 10); let arr = []; arr.push(res[a]); let option = { toolti ...

  9. cocos2x (c++/lua) spine 文件的预加载

    在之前,笔者写过一编博客,通过lua在加载场景加载spineAnimation动画精灵,保存在table中,然后在游戏中创建动画精灵时,提取加载好的spineAnimaiton中的 spSkeleto ...

  10. Linux-Java安装

    安装 yum -y install java-1.8.0-openjdk* Tomcat安装:到官网http://tomcat.apache.org/,然后找到Tomcat9下载地址 http://m ...