概述

  • aspect object programming 面向切面编程
  • 功能:可以实现“业务代码”与“关注点代码”分离
    • 关注点代码:就是指重复执行的代码
    • 业务代码:核心的业务功能
  • 运行期间,执行核心业务代码的时候动态植入关注点代码【代理】

名词解释

  • 关注点

    • 重复代码就叫关注点
  • 切面
    • 关注点形成的类,就叫做切面(类)
  • 切入点
    • 执行目标对象方法,动态植入切面代码
    • 可以通过切入点表达式,指定拦截哪些类的哪些方法,给指定的类在运行的时候植入切面类代码
  • aop
    • 面向切面编程,就是指 对很多功能都有的重复的代码的抽取,再在运行的时候往业务方法上动态植入“切面类代码”。

手动实现AOP编程

 package cn.fuyi.d_myaop;

 public interface IUserDao {

     void save();
} package cn.fuyi.d_myaop; import javax.annotation.Resource; import org.springframework.stereotype.Component; @Component("userDao")
public class UserDao implements IUserDao { @Override
public void save() {
System.out.println("=====已经保存数据====-");
}
} package cn.fuyi.d_myaop; import org.springframework.stereotype.Component; /**
* 抽取重复代码形成的类
* @author fuyi
*
*/
@Component("aop") //加入IOC容器
public class Aop { public void begin() {
System.out.println("开启事务");
} public void commit() {
System.out.println("提交事务");
}
} package cn.fuyi.d_myaop; import java.lang.reflect.Method; import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy; public class ProxyFactory { private static Object target;
private static Aop aop; public static Object getProxyInstance(Object target_, Aop aop_) { target = target_;
aop = aop_; return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() { @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
aop.begin();
//执行目标对象方法
Object returnValue = method.invoke(target, args);
aop.commit();
return returnValue;
}
});
} } bean.xml
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.fuyi.d_myaop"></context:component-scan> <!-- 调用工厂方法,返回UserDao的代理对象 -->
<bean id="userDao_proxy" class="cn.fuyi.d_myaop.ProxyFactory" factory-method="getProxyInstance">
<constructor-arg index="0" ref="userDao"></constructor-arg>
<constructor-arg index="1" ref="aop"></constructor-arg>
</bean> package cn.fuyi.d_myaop; import static org.junit.Assert.*; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { private ApplicationContext ac = new ClassPathXmlApplicationContext("cn/fuyi/d_myaop/beans.xml"); @Test
public void testAop1() throws Exception {
IUserDao ud = (IUserDao) ac.getBean("userDao_proxy");
ud.save(); }
} /**Output
开启事务
=====已经保存数据====-
提交事务
*/

注解方式实现AOP编程

步骤:

  1) 先引入aop相关jar文件    (aspectj  aop优秀组件)

      spring-aop-3.2.5.RELEASE.jar   【spring3.2源码】

      aopalliance.jar   【spring2.5源码/lib/aopalliance】

      aspectjweaver.jar   【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】

      aspectjrt.jar   【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】

    注意: 用到spring2.5版本的jar文件,如果用jdk1.7可能会有问题。需要升级aspectj组件,即使用aspectj-1.8.2版本中提供jar文件提供。

  2) bean.xml中引入aop名称空间

  3) 开启aop注解

  4) 使用注解

    @Aspect 指定一个类为切面类

    @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))")  指定切入点表达式

    @Before("pointCut_()") 前置通知: 目标方法之前执行

    @After("pointCut_()") 后置通知:目标方法之后执行(始终执行)

    @AfterReturning("pointCut_()")     返回后通知: 执行方法结束前执行(异常不执行)

    @AfterThrowing("pointCut_()") 异常通知:  出现异常时候执行

    @Around("pointCut_()") 环绕通知: 环绕目标方法执行

 package cn.fuyi.e_annoaop;

 public interface IUserDao {

     void save();
} package cn.fuyi.e_annoaop; import org.springframework.stereotype.Component; @Component("userDao")
public class UserDao implements IUserDao { @Override
public void save() {
System.out.println("=====已经保存数据====-");
}
} @Component
@Aspect // 指定当前类为切面类
public class Aop { // 指定切入点表单式: 拦截哪些方法; 即为哪些类生成代理对象 @Pointcut("execution(* cn.fuyi.e_annoaop.*.*(..))")
public void pointCut_(){
} // 前置通知 : 在执行目标方法之前执行
@Before("pointCut_()")
public void begin(){
System.out.println("开始事务/异常");
} // 后置/最终通知:在执行目标方法之后执行 【无论是否出现异常最终都会执行】
@After("pointCut_()")
public void after(){
System.out.println("提交事务/关闭");
} // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
@AfterReturning("pointCut_()")
public void afterReturning() {
System.out.println("afterReturning()");
} // 异常通知: 当目标方法执行异常时候执行此关注点代码
@AfterThrowing("pointCut_()")
public void afterThrowing(){
System.out.println("afterThrowing()");
} // 环绕通知:环绕目标方式执行
@Around("pointCut_()")
public void around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕前....");
pjp.proceed(); // 执行目标方法
System.out.println("环绕后....");
} } <!-- 开启注解扫描 -->
<context:component-scan base-package="cn.fuyi.e_annoaop"></context:component-scan> <!-- 开启aop注解方式,可不写
proxy-target-class 默认为false,如果目标对象实现了接口,就使用JDK代理,否则用Cglib代理
-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> public class App { ApplicationContext ac =
new ClassPathXmlApplicationContext("cn/itcast/e_aop_anno/bean.xml"); // 目标对象有实现接口,spring会自动选择“JDK代理”
@Test
public void testApp() {
IUserDao userDao = (IUserDao) ac.getBean("userDao");
System.out.println(userDao.getClass());
userDao.save();
} // 目标对象没有实现接口, spring会用“cglib代理”
@Test
public void testCglib() {
OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
System.out.println(orderDao.getClass());
orderDao.save();
}
}

XML方式实现AOP编程

  1) 引入jar文件  【aop 相关jar, 4个】

  2) 引入aop名称空间

  3)aop 配置

    * 配置切面类 (重复执行代码形成的类)

    * aop配置

      拦截哪些方法 / 拦截到方法后应用通知代码

 <?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:p="http://www.springframework.org/schema/p"
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"> <!-- dao 实例 -->
<bean id="userDao" class="cn.itcast.f_aop_xml.UserDao"></bean>
<bean id="orderDao" class="cn.itcast.f_aop_xml.OrderDao"></bean> <!-- 切面类 -->
<bean id="aop" class="cn.itcast.f_aop_xml.Aop"></bean> <!-- Aop配置 -->
<aop:config>
<!-- 定义一个切入点表达式: 拦截哪些方法 -->
<aop:pointcut expression="execution(* cn.itcast.f_aop_xml.*.*(..))" id="pt"/>
<!-- 切面 -->
<aop:aspect ref="aop">
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pt"/>
<!-- 前置通知: 在目标方法调用前执行 -->
<aop:before method="begin" pointcut-ref="pt"/>
<!-- 后置通知: -->
<aop:after method="after" pointcut-ref="pt"/>
<!-- 返回后通知 -->
<aop:after-returning method="afterReturning" pointcut-ref="pt"/>
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pt"/> </aop:aspect>
</aop:config>
</beans>

切入点表达式

  可以对指定的“方法”进行拦截;  从而给指定的方法所在的类生层代理对象。

 <?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:p="http://www.springframework.org/schema/p"
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"> <!-- dao 实例 -->
<bean id="userDao" class="cn.itcast.g_pointcut.UserDao"></bean>
<bean id="orderDao" class="cn.itcast.g_pointcut.OrderDao"></bean> <!-- 切面类 -->
<bean id="aop" class="cn.itcast.g_pointcut.Aop"></bean> <!-- Aop配置 -->
<aop:config> <!-- 定义一个切入点表达式: 拦截哪些方法 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>--> <!-- 【拦截所有public方法】 -->
<!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>--> <!-- 【拦截所有save开头的方法 】 -->
<!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>--> <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
<!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>--> <!-- 【拦截指定类的所有方法】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>--> <!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
<!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>--> <!-- 【多个表达式】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!-- 下面2个且关系的,没有意义 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) &amp;&amp; execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!-- 【取非值】 -->
<!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->

 

spring来了-04-AOP的更多相关文章

  1. Spring 框架基础(04):AOP切面编程概念,几种实现方式演示

    本文源码:GitHub·点这里 || GitEE·点这里 一.AOP基础简介 1.切面编程简介 AOP全称:Aspect Oriented Programming,面向切面编程.通过预编译方式和运行期 ...

  2. Spring的IOC和AOP之深剖

    今天,既然讲到了Spring 的IOC和AOP,我们就必须要知道 Spring主要是两件事: 1.开发Bean:2.配置Bean.对于Spring框架来说,它要做的,就是根据配置文件来创建bean实例 ...

  3. Spring(6)—— AOP

    AOP(Aspect-OrientedProgramming)面向切面编程,与OOP完全不同,使用AOP编程系统被分为切面或关注点,而不是OOP中的对象. AOP的引入 在OOP面向对象的使用中,无可 ...

  4. 转-Spring Framework中的AOP之around通知

    Spring Framework中的AOP之around通知 http://blog.csdn.net/xiaoliang_xie/article/details/7049183 标签: spring ...

  5. spring的IOC和AOP

     spring的IOC和AOP 1.解释spring的ioc? 几种注入依赖的方式?spring的优点? IOC你就认为他是一个生产和管理bean的容器就行了,原来需要在调用类中new的东西,现在都是 ...

  6. spring之初识Ioc&Aop

    Spring框架的作用 spring是一个轻量级的企业级框架,提供了ioc容器.Aop实现.dao/orm支持.web集成等功能,目标是使现有的java EE技术更易用,并促进良好的编程习惯. Spr ...

  7. [置顶] 深入浅出Spring(三) AOP详解

    上次的博文深入浅出Spring(二) IoC详解中,我为大家简单介绍了一下Spring框架核心内容中的IoC,接下来我们继续讲解另一个核心AOP(Aspect Oriented Programming ...

  8. Spring学习笔记4——AOP

    AOP 即 Aspect Oriented Program 面向切面编程 首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能. 所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务 ...

  9. Spring 的IOC和AOP总结

    Spring 的IOC和AOP IOC 1.IOC 许多应用都是通过彼此间的相互合作来实现业务逻辑的,如类A要调用类B的方法,以前我们都是在类A中,通过自身new一个类B,然后在调用类B的方法,现在我 ...

  10. Spring中IOC和AOP的详细解释(转)

    原文链接:Spring中IOC和AOP的详细解释 我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入,和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂 ...

随机推荐

  1. ruby学习总结01

    1.ruby的两种运行方式:ruby方式咋(在命令行中输入ruby xxx.rb)和irb方式(在命令行中输入 irb) 注意:可以在命令后添加 -E UTF-8 指定编码格式 例:ruby -E U ...

  2. C++实现链式栈,运用模板,界面友好,操作方便,运行流畅

    //.h文件 #ifndef STACK_H #define STACK_H #include<iostream> #include<iomanip> using namesp ...

  3. 数独Sudoku

    数独(すうどく,Sūdoku),是源自18世纪瑞士发明,流传到美国,再由日本发扬光大的一种数学游戏.是一种运用纸.笔进行演算的逻辑游戏.玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并 ...

  4. sqlite中的自增主键

    http://stackoverflow.com/questions/8519936/sqlite-autoincrement-primary-key-questions I'm not sure w ...

  5. Django的Many-to-Many(多对多)模型

      Django的Many-to-Many(多对多)模型 日期:2012-05-05 |  来源:未知 |  作者:redice |  人围观 |  1 人鼓掌了! 鲲鹏Web数据抓取 - 专业Web ...

  6. Codeforces Round #382 (Div. 2) C. Tennis Championship 斐波那契

    C. Tennis Championship time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  7. jsp get方式请求参数中包含中文乱码问题解决

    1. 自己接收到参数之后在后台进行转码处理 2: 修改tomcat的配置文件  server.xml <Connector port="8080" protocol=&quo ...

  8. sp_getTable_data

    CREATE PROC sp_Select_Table ) AS begin ) SET @sql='SELECT * FROM ' + @TableName EXEC (@sql) end GO

  9. 【T-SQL系列】新的排序函数

    如:ROW_NUMBER.RANK.DENSE_RANK三个分析函数都是按照col1分组内从1开始排序 ROW_NUMBER() 是没有重复值的排序(即使两天记录相等也是不重复的),可以利用它来实现分 ...

  10. img_jquerydim