zoukankan      html  css  js  c++  java
  • spring来了-04-AOP

    概述

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

     

    名词解释

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

     

    手动实现AOP编程

      1 package cn.fuyi.d_myaop;
      2 
      3 public interface IUserDao {
      4 
      5     void save();
      6 }
      7 
      8 package cn.fuyi.d_myaop;
      9 
     10 import javax.annotation.Resource;
     11 
     12 import org.springframework.stereotype.Component;
     13 
     14 @Component("userDao")
     15 public class UserDao implements IUserDao {
     16     
     17     @Override
     18     public void save() {
     19         System.out.println("=====已经保存数据====-");
     20     }
     21 }
     22 
     23 package cn.fuyi.d_myaop;
     24 
     25 import org.springframework.stereotype.Component;
     26 
     27 /**
     28  * 抽取重复代码形成的类
     29  * @author fuyi
     30  *
     31  */
     32 @Component("aop")   //加入IOC容器
     33 public class Aop {
     34     
     35     public void begin() {
     36         System.out.println("开启事务");
     37     }
     38     
     39     public void commit() {
     40         System.out.println("提交事务");
     41     }
     42 }
     43 
     44 package cn.fuyi.d_myaop;
     45 
     46 import java.lang.reflect.Method;
     47 
     48 import org.springframework.cglib.proxy.InvocationHandler;
     49 import org.springframework.cglib.proxy.Proxy;
     50 
     51 public class ProxyFactory {
     52 
     53     private static Object target;
     54     private static Aop aop;
     55     
     56     public static Object getProxyInstance(Object target_, Aop aop_) {
     57         
     58         target = target_;
     59         aop = aop_;
     60         
     61         return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
     62                 target.getClass().getInterfaces(), 
     63                 new InvocationHandler() {
     64                     
     65                     @Override
     66                     public Object invoke(Object proxy, Method method, Object[] args)
     67                             throws Throwable {
     68                         aop.begin();
     69                         //执行目标对象方法
     70                         Object returnValue = method.invoke(target, args);
     71                         aop.commit();
     72                         return returnValue;
     73                     }
     74                 });
     75     }
     76     
     77 }
     78 
     79 bean.xml
     80     <!-- 开启注解扫描 -->
     81     <context:component-scan base-package="cn.fuyi.d_myaop"></context:component-scan>
     82     
     83     <!-- 调用工厂方法,返回UserDao的代理对象 -->
     84     <bean id="userDao_proxy" class="cn.fuyi.d_myaop.ProxyFactory" factory-method="getProxyInstance">
     85         <constructor-arg index="0" ref="userDao"></constructor-arg>
     86         <constructor-arg index="1" ref="aop"></constructor-arg>
     87     </bean>
     88 
     89 package cn.fuyi.d_myaop;
     90 
     91 import static org.junit.Assert.*;
     92 
     93 import org.junit.Test;
     94 import org.springframework.context.ApplicationContext;
     95 import org.springframework.context.support.ClassPathXmlApplicationContext;
     96 
     97 public class App {
     98 
     99     private ApplicationContext ac = new ClassPathXmlApplicationContext("cn/fuyi/d_myaop/beans.xml");
    100     
    101     @Test
    102     public void testAop1() throws Exception {
    103         IUserDao ud = (IUserDao) ac.getBean("userDao_proxy");
    104         ud.save();
    105 
    106     }
    107 }
    108 
    109 /**Output
    110 开启事务
    111 =====已经保存数据====-
    112 提交事务
    113 */
    View Code

    注解方式实现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.2lib】

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

        注意: 用到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_()") 环绕通知: 环绕目标方法执行

     1 package cn.fuyi.e_annoaop;
     2 
     3 public interface IUserDao {
     4 
     5     void save();
     6 }
     7 
     8 package cn.fuyi.e_annoaop;
     9 
    10 import org.springframework.stereotype.Component;
    11 
    12 @Component("userDao")
    13 public class UserDao implements IUserDao {
    14     
    15     @Override
    16     public void save() {
    17         System.out.println("=====已经保存数据====-");
    18     }
    19 }
    20 
    21 
    22 @Component
    23 @Aspect  // 指定当前类为切面类
    24 public class Aop {
    25 
    26     // 指定切入点表单式: 拦截哪些方法; 即为哪些类生成代理对象
    27     
    28     @Pointcut("execution(* cn.fuyi.e_annoaop.*.*(..))")
    29     public void pointCut_(){
    30     }
    31     
    32     // 前置通知 : 在执行目标方法之前执行
    33     @Before("pointCut_()")
    34     public void begin(){
    35         System.out.println("开始事务/异常");
    36     }
    37     
    38     // 后置/最终通知:在执行目标方法之后执行  【无论是否出现异常最终都会执行】
    39     @After("pointCut_()")
    40     public void after(){
    41         System.out.println("提交事务/关闭");
    42     }
    43     
    44     // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
    45     @AfterReturning("pointCut_()")
    46     public void afterReturning() {
    47         System.out.println("afterReturning()");
    48     }
    49     
    50     // 异常通知: 当目标方法执行异常时候执行此关注点代码
    51     @AfterThrowing("pointCut_()")
    52     public void afterThrowing(){
    53         System.out.println("afterThrowing()");
    54     }
    55     
    56     // 环绕通知:环绕目标方式执行
    57     @Around("pointCut_()")
    58     public void around(ProceedingJoinPoint pjp) throws Throwable{
    59         System.out.println("环绕前....");
    60         pjp.proceed();  // 执行目标方法
    61         System.out.println("环绕后....");
    62     }
    63     
    64 }
    65 
    66 
    67     <!-- 开启注解扫描 -->
    68     <context:component-scan base-package="cn.fuyi.e_annoaop"></context:component-scan>
    69     
    70     <!-- 开启aop注解方式,可不写
    71         proxy-target-class 默认为false,如果目标对象实现了接口,就使用JDK代理,否则用Cglib代理
    72     -->
    73     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    74 
    75 
    76 public class App {
    77     
    78     ApplicationContext ac = 
    79         new ClassPathXmlApplicationContext("cn/itcast/e_aop_anno/bean.xml");
    80 
    81     // 目标对象有实现接口,spring会自动选择“JDK代理”
    82     @Test
    83     public void testApp() {
    84         IUserDao userDao = (IUserDao) ac.getBean("userDao");
    85         System.out.println(userDao.getClass());
    86         userDao.save();
    87     }
    88     
    89     // 目标对象没有实现接口, spring会用“cglib代理”
    90     @Test
    91     public void testCglib() {
    92         OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
    93         System.out.println(orderDao.getClass());
    94         orderDao.save();
    95     }
    96 }
    View Code

    XML方式实现AOP编程

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

      2) 引入aop名称空间

      3)aop 配置

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

        * aop配置

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

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:p="http://www.springframework.org/schema/p"
     5     xmlns:context="http://www.springframework.org/schema/context"
     6     xmlns:aop="http://www.springframework.org/schema/aop"
     7     xsi:schemaLocation="
     8         http://www.springframework.org/schema/beans
     9         http://www.springframework.org/schema/beans/spring-beans.xsd
    10         http://www.springframework.org/schema/context
    11         http://www.springframework.org/schema/context/spring-context.xsd
    12         http://www.springframework.org/schema/aop
    13         http://www.springframework.org/schema/aop/spring-aop.xsd">
    14     
    15     <!-- dao 实例 -->
    16     <bean id="userDao" class="cn.itcast.f_aop_xml.UserDao"></bean>
    17     <bean id="orderDao" class="cn.itcast.f_aop_xml.OrderDao"></bean>
    18     
    19     <!-- 切面类 -->
    20     <bean id="aop" class="cn.itcast.f_aop_xml.Aop"></bean>
    21     
    22     <!-- Aop配置 -->
    23     <aop:config>
    24         <!-- 定义一个切入点表达式: 拦截哪些方法 -->
    25         <aop:pointcut expression="execution(* cn.itcast.f_aop_xml.*.*(..))" id="pt"/>
    26         <!-- 切面 -->
    27         <aop:aspect ref="aop">
    28             <!-- 环绕通知 -->
    29             <aop:around method="around" pointcut-ref="pt"/>
    30             <!-- 前置通知: 在目标方法调用前执行 -->
    31             <aop:before method="begin" pointcut-ref="pt"/>
    32             <!-- 后置通知: -->
    33             <aop:after method="after" pointcut-ref="pt"/>
    34             <!-- 返回后通知 -->
    35             <aop:after-returning method="afterReturning" pointcut-ref="pt"/>
    36             <!-- 异常通知 -->
    37             <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
    38             
    39         </aop:aspect>
    40     </aop:config>
    41 </beans>  
    View Code

    切入点表达式

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

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:p="http://www.springframework.org/schema/p"
     5     xmlns:context="http://www.springframework.org/schema/context"
     6     xmlns:aop="http://www.springframework.org/schema/aop"
     7     xsi:schemaLocation="
     8         http://www.springframework.org/schema/beans
     9         http://www.springframework.org/schema/beans/spring-beans.xsd
    10         http://www.springframework.org/schema/context
    11         http://www.springframework.org/schema/context/spring-context.xsd
    12         http://www.springframework.org/schema/aop
    13         http://www.springframework.org/schema/aop/spring-aop.xsd">
    14     
    15     <!-- dao 实例 -->
    16     <bean id="userDao" class="cn.itcast.g_pointcut.UserDao"></bean>
    17     <bean id="orderDao" class="cn.itcast.g_pointcut.OrderDao"></bean>
    18     
    19     <!-- 切面类 -->
    20     <bean id="aop" class="cn.itcast.g_pointcut.Aop"></bean>
    21     
    22     <!-- Aop配置 -->
    23     <aop:config>
    24         
    25         <!-- 定义一个切入点表达式: 拦截哪些方法 -->
    26         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>-->
    27         
    28         <!-- 【拦截所有public方法】 -->
    29         <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->
    30         
    31         <!-- 【拦截所有save开头的方法 】 -->
    32         <!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->
    33         
    34         <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
    35         <!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>-->
    36         
    37         <!-- 【拦截指定类的所有方法】 -->
    38         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>-->
    39         
    40         <!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
    41         <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->
    42         
    43         <!-- 【多个表达式】 -->
    44         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
    45         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
    46         <!-- 下面2个且关系的,没有意义 -->
    47         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) &amp;&amp; execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
    48         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
    49         
    50         <!-- 【取非值】 -->
    51         <!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
    View Code

     

  • 相关阅读:
    syslog日志格式解析
    Linux打补丁的一个简单例子
    Linux打补丁的一些问题
    安全漏洞整改解决方案(很不错网络文章)
    Linux系统启动过程
    chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息
    主机名/etc/hosts文件的作用
    Linux中如何配置IP相关文件
    /bin、/sbin、/usr/bin、/usr/sbin目录Linux执行文档的区别
    日志生成控制文件syslog.conf
  • 原文地址:https://www.cnblogs.com/fuyiming/p/5830282.html
Copyright © 2011-2022 走看看