一、什么叫做AOp

  解析:Aop(Aspect Oriented Programming)是面向切面编程,软件编程的一种思想。

     OOp(Object Oriented Programming)是面向对象编程。

     Aop是基于OOp的,又高于OOp。

二、区别

  面向对象编程是从【静态角度】考虑程序的结构,而面向切面编程是从【动态角度】考虑程序运行过程。
  AOP底层,就是采用【动态代理】模式实现的。采用了两种代理:JDK动态代理和CGLIB动态代理。

三、切入点表达式

execution(【modifiers-pattern?】 访问修饰符
ret-type-pattern 返回值类型
【declaring-type-pattern?】 全限定性类名
name-pattern(param-pattern) 方法名(参数名) 包名.类型名.方法名
【throws-pattern?】) 抛出异常类型
public void doLog(String log){

}
方法签名
切入点表达式要匹配的对象就是目标方法的方法名。所以,execution表达式中明显就是方法的签名。注意:表达式中加[]的部分表示可省略部分,各部分间用空格分开。在其中可以使用以下符号:
符号 意义
* 0至多个任意字符
.. 用在方法参数中,表示任意多个参数
用在包名后,表示当前包及其子包路径
+ 用在类名后,表示当前类及其子类
用在接口后,表示当前接口及其实现类
案例:
execution(public * *(..)) 指定切入点为:任意公共方法
execution(* set*(..)) 指定切入点为:任何一个以"set"开始的方法

四、基本术语(一些名词):

(1)切面(Aspect)
切面泛指[*交叉业务逻辑*]。事务处理和日志处理可以理解为切面。常用的切面有通知(Advice)与顾问(Advisor)。实际就是对主业务逻辑的一种增强。

(2)织入(Weaving)
织入是指将切面代码插入到目标对象的过程。代理的invoke方法完成的工作,可以称为织入。

(3) 连接点(JoinPoint) 
连接点是指可以被切面织入的方法。通常业务接口的方法均为连接点

(4)切入点(PointCut)
切入点指切面具体织入的方法
注意:被标记为final的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。

(5)目标对象(Target)
目标对象指将要被增强的对象。即包含主业务逻辑的类的对象。

(6)通知(Advice) 
通知是切面的一种实现,可以完成简单的织入功能。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是执行之后执行等。切入点定义切入的位置,通知定义切入的时间。

(7)顾问(Advisor)
顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。

五、Spring的经典AOP配置方案

  1、使用的是Aspectj第三方框架,实现了AOP思想Xml

  2、注解配置的AOP

  3、纯POJO  就是一个普通的类<aop:config>

  4、代理工厂模式就是最原始的一种

(一)首先我们介绍的是纯POJO(通过POJO来实现一个前置增强类)

首先我们先新建一个web项目我们分别在src下面新建包

其次我们引入我们需要的包

接下来我们定一个普通的UserBiz类

package cn.happy.biz;

public class UserBiz {
public void addStu(UserInf user){
System.out.println("add ok");
}
}

我们在aop包下BeforeAdvice前置增强类,它需要实现

MethodBeforeAdvice接口的before方法
package cn.happy.aop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

/**
* before
* @author Happy
*
*/
public class BeforeAdvice implements MethodBeforeAdvice{ /**
*
* @param method 被代理的目标的方法
* @param args 传递给目标方法的参数
* @param obj 被代理的目标对象 * @throws Throwable
*/
@Override
public void before(Method method, Object[] args , Object obj)
throws Throwable {
System.out.println("========before======");
}

我们接下来写配置文件(注意引入的命名空间)<aop:config>配置下实现切面

<?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"
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.xsd
"> <bean id="biz" class="cn.happy.biz.UserBiz"></bean> <!-- 前置 -->
<bean id="beforeAdvice" class="cn.happy.aop.BeforeAdvice"></bean>

<!-- aop配置切面 -->
<aop:config>
<!-- 定义切点 -->
<aop:pointcut expression="execution(public void *(cn.happy.biz.UserInf))" id="pointcut"/>
<!-- 增强处理和切点结合 -->
<aop:advisor advice-ref="beforeAdvice" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterAdivice" pointcut-ref="pointcut"/>
</aop:config>

测试类

@Test
public void testOne(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserBiz biz = (UserBiz)ctx.getBean("biz");
biz.addStu(new UserInf()); }

(二)用注解配置的AOP(五种通知:前置通知,后置通知,返回通知,异常通知,环绕通知)

如上图所示建立包和类i

引入上图夹包

定一个接口

package cn.happy.enetity;
/**
* 1.业务接口
* @author Happy
*
*/
public interface ISomeService {
//1.1 执行事务
public void doTransaction();
//1.2 书写日志
public String doLog();
}

一定一个实现接口的实现类

package cn.happy.enetity;

public class SomeServiceImpl implements ISomeService {

    public void doTransaction() {
System.out.println("开启事务");
} public String doLog() {
System.out.println("书写日志"+/);
return "我是书写日志的返回值哦!!!!!";
} }

定一个增强类用注解写

package cn.happy.aspece;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; @Aspect
public class MyAspect {
//前置通知
@Before(value="execution(public * *(..))")
public void MyBefore(){
System.out.println("这是前置通知哦!!!!!!!在执行目标对象之前执行");
} //后置通知
@AfterReturning(value="execution(public * *(..))")
public void MyAfterReturning(){
System.out.println("这是后置通知哦!!!!!!!在执行目标对象之前执行");
} //环绕通知
/* @Around(value="execution(public * *(..))")
public void MyAround(ProceedingJoinPoint pjp){
System.out.println("这是环绕通知前哦!!!!!!!在执行目标对象之前执行");
try {
pjp.proceed();
System.out.println("这是环绕通知后哦!!!!!!!在执行目标对象之前执行");
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/ //异常通知
@AfterThrowing(value="execution(public * *(..))")
public void MyAfterThrowing(){
System.out.println("这是异常通知哦!!!!!!!在执行目标对象之前执行");
} //最终通知
@After(value="execution(public * *(..))")
public void MyAfter(){
System.out.println("这是最终通知哦!!!!!!!在执行目标对象之前执行");
}
}

配置文件

<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 目标对象 -->
<bean id="someService" class="cn.happy.enetity.SomeServiceImpl"></bean> <!-- 切面: -->
<bean id="myAspect" class="cn.happy.aspece.MyAspect"></bean>
<!--aop:aspectj可以启动对@AspectJ注解支持-->
<aop:aspectj-autoproxy/>
</beans>

测试类

package cn.happy.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.happy.enetity.ISomeService; public class Spring_01Test {
@Test
public void testOne(){ ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
ISomeService service = (ISomeService)ctx.getBean("someService");
service.doTransaction();
String result = service.doLog();
System.out.println(result);
}
}

(三)使用的是Aspectj第三方框架,实现了AOP思想XML的方式(就是一个普通类通过配置实现 )

如图所示建立包和类引入包同上

定一个接口

package enetity;
/**
* 1.业务接口
* @author Happy
*
*/
public interface ISomeService {
//1.1 执行事务
public void doTransaction();
//1.2 书写日志
public String doLog();
}

定义一个实现类

package enetity;

public class SomeServiceImpl implements ISomeService {

    public void doTransaction() {
System.out.println("开启事务");
} public String doLog() {
/*System.out.println("书写日志"+5/0);*/
System.out.println("书写日志");
return "我是书写日志的返回值哦!!!!!";
} }

定一个增强类就是一个普通类通过配置实现

package aspece;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspect {
// 前置通知execution(public * *(..))
public void MyBefore() {
System.out.println("这是前置通知哦!!!!!!!在执行目标对象之前执行");
} // 后置通知execution(public * *(..))
public void MyAfterReturning() {
System.out.println("这是后置通知哦!!!!!!!在执行目标对象之前执行");
} // 异常通知
public void MyAfterThrowing() {
System.out.println("这是异常通知哦!!!!!!!在执行目标对象之前执行");
} // 最终通知
public void MyAfter() {
System.out.println("这是最终通知哦!!!!!!!在执行目标对象之前执行");
} //环绕通知
public String MyAround(ProceedingJoinPoint pjp){
System.out.println("这是环绕通知前哦!!!!!!!在执行目标对象之前执行");
try {
Object result=pjp.proceed();
System.out.println("这是环绕通知后哦!!!!!!!在执行目标对象之前执行");
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "result";
}
}

配置文件

<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 目标对象 -->
<bean id="someService" class="enetity.SomeServiceImpl"></bean> <!-- 切面: -->
<bean id="myAspect" class="aspece.MyAspect"></bean> <!-- aop的配置 -->
<aop:config>
<!-- 切点 -->
<aop:pointcut expression="execution(public * *(..))" id="dopointcut"/>
<aop:aspect ref="myAspect"> <aop:before method="MyBefore" pointcut-ref="dopointcut"/>
<aop:after-returning method="MyAfterReturning" pointcut-ref="dopointcut"/>
<!-- <aop:after-throwing method="MyAfterThrowing" pointcut-ref="dopointcut"/> -->
<aop:after method="MyAfter" pointcut-ref="dopointcut"/>
<aop:around method="MyAround" pointcut-ref="dopointcut"/>
</aop:aspect> </aop:config>
</beans>

测试类

@Test
public void testOne(){ ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
ISomeService service = (ISomeService)ctx.getBean("someService");
service.doTransaction();
String result = service.doLog();
System.out.println(result);
}

(四)代理工厂模式就是最原始的一种

如图所示建立包和类

定义一个接口

package cn.happy.service;

public interface ISomeService {
// 執行事務
public void doTransaction(); // 記錄日誌
public String doLog();
}

定义一个实现类

package cn.happy.service;

public class ISomeServiceImpl implements ISomeService{
//目标方法
public void doTransaction() {
System.out.println("开启事务"); } public String doLog() {
System.out.println("记录日志");
return null;
} }

定义一个增强类

package cn.happy.aop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;
/*
.前置通知 MethodBeforeAdvice
定义前置通知,需要实现MethodBeforeAdvice接口,
该接口中有一个方法before(),会在目标方法执行之前执行。
*/
public class MyMethodBeforeAdvice implements MethodBeforeAdvice { public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("Before"); } }

配置实现一个前置通知

<?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"
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.1.xsd
">
<!-- 业务对象 -->
<bean id="someService" class="cn.happy.service.ISomeServiceImpl" />
<!-- 交叉业务 -->
<bean id="beforeAdivce" class="cn.happy.aop.MyMethodBeforeAdvice" />
<!-- 代理对象 -->
<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetName" value="someService" />
<property name="interceptorNames" value="beforeAdivce,afterAdivce" />
</bean>
</beans>

测试类

package cn.happy.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.happy.service.ISomeService;
import cn.happy.service.ISomeService1; public class Test1 {
@Test
public void testOne(){ ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
ISomeService service = (ISomeService)ctx.getBean("serviceProxy");
service.doTransaction();
service.doLog(); }
}

  

初识Aop和扩展Aop的更多相关文章

  1. IOC和AOP使用扩展之AOP详解实现类

    摘要:   “Depend on yourself” is what nature says to every man.  Parents can help you. Teachers can hel ...

  2. (转)使用CGLIB实现AOP功能与AOP概念解释

    http://blog.csdn.net/yerenyuan_pku/article/details/52864395 使用CGLIB实现AOP功能 在Java里面,我们要产生某个对象的代理对象,这个 ...

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

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

  4. 死磕Spring之AOP篇 - Spring AOP注解驱动与XML配置

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

  5. Chapter 4: Spring and AOP:Spring's AOP Framework -- draft

    Spring's AOP Framework Let's begin by looking at Spring's own AOP framework - a proxy-based framewor ...

  6. <aop:aspect>与<aop:advisor>的区别

    在开发过程中,不少有Spring Aop的使用,在面向切面编程时,我们会使用< aop:aspect>:在进行事务管理时,我们会使用< aop:advisor>.那么,对于&l ...

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

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

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

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

  9. 【SSH进阶之路】Spring的AOP逐层深入——AOP的基本原理(六)

    经过我们对Spring的IOC不断的深入学习,Spring的面貌逐渐变得清晰,我们对Spring的了解也更加的深入.从这篇博文开始我们学习Spring的第二大核心内容:AOP. 什么是AOP AOP( ...

随机推荐

  1. ViewPager 的页面重置问题

    当我们使用ViewPager控件时,假设我们的ViewPager有三页,当我们第一次启动ViewPager显示第一页的时候,ViewPager会预加载第二页,这样当我们向第二页滑动的时候就可以看见第二 ...

  2. 如何优雅的使用vue+vux开发app -02

    如何优雅的使用vue+vux开发app -02 很明显这又是一个错误的示范,请勿模仿 使用动态组件实现保留状态的路由 <!DOCTYPE html> <html> <he ...

  3. MongoDB更新文档

    说明:来看一下关系型数据库的update语句 UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某 其中where子句就类似查询文本,定位要更改的子表,set子句类似于修改器,更 ...

  4. JAVA设计模式《二》

    上一篇为大家介绍了一下设计模式中的责任链模式,本篇为大家介绍一下关于设计模式中的单例模式与模板方法模式.单例模式的作用在于,保证应用中某个实例有且只有一个,单例模式又被分为:饱汉模式与饿汉模式,两者的 ...

  5. AIX下如何根据端口号查找相应的进程

    1. $ netstat -Aan |grep 8080 f1000e0002321bb8 tcp 0 0 *.8080 *.* LISTEN 2. $ rmsock f1000e0002321bb8 ...

  6. LoRaWAN协议(六)--OTAA KEY生成过程

    前言 通过OTAA方式入网的设备,通讯时使用的KEY需要通过服务器获得,在入网之间,设备无法通讯. 相关的OTAA入网流程已经在上一章中讲解过了,有兴趣的可以去看看**LoRaWAN协议(五)__OT ...

  7. Quartz Java resuming a job excecutes it many times--转

    原文地址:http://stackoverflow.com/questions/1933676/quartz-java-resuming-a-job-excecutes-it-many-times Q ...

  8. [转载]基于TFS实践敏捷-项目管理

    最近,一直想让团队加入敏捷开发,但TFS2010用下来,并不是令人满意,还好,TFS2012横空出世了.相比TFS2010,TFS2012改进太多了,主要体现在以下方面: Team Web Acces ...

  9. Pillow实现图片对比

    在编写Web自动化测试用例的时候,如何写断言使新手不解,严格意义上来讲,没有断言的自动化脚本不能叫测试用例.就像功能测试一样,当测试人员做了一些操作之后必然会判断实际结果是否等于预期结果,只不过,这个 ...

  10. Intention.js – 动态重构 HTML 为响应式模式

    Intention.js 提供一个轻量级的和明确的方式,帮助你动态重组 HTML,成为响应式的方式.操作方法都放在了元素自己里面,所以灵活的布局看起来就似乎不会那么的抽象和凌乱. 您可以轻松地增加布局 ...