zoukankan      html  css  js  c++  java
  • Spring框架总结(九)

    三、AOP编程

    关注点代码:除了业务代码以外的代码.比如开启事务,关闭事务,异常处理
    核心业务代码:保存用户这一句才是重点.
    例子如下:
    // 保存一个用户
    public void add(User user) {
    Session session = null;
    Transaction trans = null;
    try {
    session = HibernateSessionFactoryUtils.getSession(); // 【关注点代码】
    trans = session.beginTransaction(); // 【关注点代码】

    session.save(user); // 核心业务代码

    trans.commit(); //…【关注点代码】

    } catch (Exception e) {
    e.printStackTrace();
    if(trans != null){
    trans.rollback(); //..【关注点代码】

    }
    } finally{
    HibernateSessionFactoryUtils.closeSession(session); ////..【关注点代码】

    }
    }

    为了提高代码效率,会让核心代码和业务代码分离.实现的方法就是代理模式.

    名词解释:
    AOP面向切面编程:
    让关注点代码与业务代码分离(面向切面编程就是面向重复代码编程)
    关注点:
    很多重复代码形成的类和方法

    切面:
    关注点形成的类。(公共的类)
    面向切面编程与面向接口编程:
    面向切面编程比面向接口编程更加抽象,面向切面编程公有属性和行为,抽象为面向切面。
    面向接口编程,各个对象的公共方法抽取出来,放到父类和接口当中,接口当中定义类的公用行为。
    面向切面编程很多重复的功能,抽象出来,比如工厂类
    应用:
    面向切面编程用在后期优化的时候使用。
    切入点(指定拦截的是哪个点,拦截哪些方法):
    执行目标对象方法,动态植入切面代码。
    可以通过切入点表达式,指定拦截哪些类的哪些方法。给指定的类在运行的时候植入切面类代码


    Aop代理实现了两种,一种是jdk代理,一种是cglib代理.
    Aop实现的其实是通过,切面类的拦截,从而进行动态代理,使得多个重复的代码和方法,抽象出来,增强代码的强壮性和代码的优化性能.

    1、注解方式实现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名称空间

     1 <context:component-scan base-package="com.liuyang.annotation.proxy"></context:component-scan> 

    3) 开启aop注解

     1 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 

    4) 使用注解
    @Aspect 指定一个类为切面类
    @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入点表达式

    @Before("pointCut_()") 前置通知: 目标方法之前执行
    @After("pointCut_()") 后置通知:目标方法之后执行(始终执行)
    @AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)
    @AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行
    @Around("pointCut_()") 环绕通知: 环绕目标方法执行

    事例:

    (1)建立UserDao

    1    public interface UserDao {
    2 
    3     public void save();
    4 
    5 }

    (2)建立MyUserDaoAop

    1    @Component
    2 public class MyUserDaoAop implements UserDao {
    3 
    4     @Override
    5     public void save() {
    6         System.out.println("******核心业务的实现*****");
    7     }
    8 
    9 }

    (3)建立AOP

     1    @Component
     2 // 指定当前类为切面类
     3 @Aspect
     4 public class Aop {
     5 
     6     // 指定切入点表单式: 拦截哪些方法; 即为哪些类生成代理对象
     7     @Pointcut("execution(* com.liuyang.annotation.proxy.*.*(..))")
     8     public void pointCut_() {
     9     }
    10 
    11     // 前置通知 : 在执行目标方法之前执行
    12     @Before("pointCut_()")
    13     public void begin() {
    14         System.out.println("开始事务/异常");
    15     }
    16 
    17     // 后置/最终通知:在执行目标方法之后执行 【无论是否出现异常最终都会执行】
    18     @After("pointCut_()")
    19     public void after() {
    20         System.out.println("提交事务/关闭");
    21     }
    22 
    23     // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
    24     @AfterReturning("pointCut_()")
    25     public void afterReturning() {
    26         System.out.println("afterReturning()");
    27     }
    28 
    29     // 异常通知: 当目标方法执行异常时候执行此关注点代码
    30     @AfterThrowing("pointCut_()")
    31     public void afterThrowing() {
    32         System.out.println("afterThrowing()");
    33     }
    34 
    35     // 环绕通知:环绕目标方式执行
    36     @Around("pointCut_()")
    37     public void around(ProceedingJoinPoint pjp) throws Throwable {
    38         System.out.println("环绕前....");
    39         pjp.proceed(); // 执行目标方法
    40         System.out.println("环绕后....");
    41     }
    42 
    43 }

    (4)建立bean.xml

     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" xmlns:p="http://www.springframework.org/schema/p"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:aop="http://www.springframework.org/schema/aop"
     6     xsi:schemaLocation="
     7         http://www.springframework.org/schema/beans
     8         http://www.springframework.org/schema/beans/spring-beans.xsd
     9         http://www.springframework.org/schema/context
    10         http://www.springframework.org/schema/context/spring-context.xsd
    11         http://www.springframework.org/schema/aop
    12         http://www.springframework.org/schema/aop/spring-aop.xsd">
    13 
    14     <!-- 开启注解扫描 -->
    15     <context:component-scan base-package="com.liuyang.annotation.proxy"></context:component-scan>
    16 
    17     <!-- 开启AOP注解模式 ,默认false采用jdk代理 -->
    18     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    19 </beans>      

    (5)建立非接口模式的代理

    1    @Component
    2 // 加入容器
    3 @Scope("prototype")
    4 public class OrderDao {
    5 
    6     public void save() {
    7         System.out.println("-----核心业务:保存2222!!!------");
    8     }
    9 }

    (6)建立测试

     1     public class TestAop {
     2 
     3     // 目标对象有实现接口,spring会自动选择“JDK代理”
     4     @Test
     5     public void testApp() {
     6         ApplicationContext aContext = new ClassPathXmlApplicationContext(
     7                 "com/liuyang/annotation/proxy/bean.xml");
     8         UserDao userDao = (UserDao) aContext.getBean("myUserDaoAop");
     9         System.out.println(userDao.getClass());// $Proxy001
    10         userDao.save();
    11     }
    12 
    13     // 目标对象没有实现接口, spring会用“cglib代理”
    14     @Test
    15     public void testCglib() {
    16         ApplicationContext aContext = new ClassPathXmlApplicationContext(
    17                 "com/liuyang/annotation/proxy/bean.xml");
    18         OrderDao orderDao = (OrderDao) aContext.getBean("orderDao");
    19         System.out.println(orderDao.getClass());
    20         orderDao.save();
    21     }
    22 
    23     @Deprecated
    24     // 共性问题:如果目标对象有实现接口,在从容器中获取目标对象的时候,只能通过接口接收对象。
    25     public void testApp2() {
    26         ApplicationContext aContext = new ClassPathXmlApplicationContext(
    27                 "com/liuyang/annotation/proxy/bean.xml");
    28         // 错误代码: 只能用接口接收
    29         UserDao userDao = (UserDao) aContext.getBean("myUserDaoAop");
    30         System.out.println(userDao.getClass());// $Proxy001
    31         userDao.save();
    32     }
    33 
    34     @Test
    35     public void testGetObj() throws Exception {
    36         ApplicationContext aContext = new ClassPathXmlApplicationContext(
    37                 "com/liuyang/annotation/proxy/bean.xml");
    38         OrderDao orderDao1 = (OrderDao) aContext.getBean("orderDao");
    39         OrderDao orderDao2 = (OrderDao) aContext.getBean("orderDao");
    40 
    41         System.out.println(orderDao1);
    42         System.out.println(orderDao2);
    43 
    44     }
    45 
    46 }
  • 相关阅读:
    PHP中可执行代码小结
    HTTP请求头列举
    GET 和 POST详解
    利用kali自带的木马工具来远程控制服务器
    利用PHP木马,远程链接服务器
    利用sqlmap暴力破解数据库密码
    MIT线性代数课程 总结与理解-第一部分
    [转]MFC debug 调试信息的输出
    关于利用均匀分布随机变量产生任意分布变量的实现
    关于string转整数
  • 原文地址:https://www.cnblogs.com/liuyangfirst/p/6556121.html
Copyright © 2011-2022 走看看