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


    摘要:

     
    “Depend on yourself” is what nature says to every man.  Parents can help you. Teachers can help you. others still can help you. But all these only help you to help yourself

      “自立”是自然对每个人的要求.也许你的父母、老师能够帮助你,其他人也可以帮助你,但是所有这些人都只是帮你更加自主、自立。

    最近完结了有关于AOP相关知识的学习,接下来就给大家讲讲我对AOP的一些见解。

    既然学习AOP大家知道AOP是什么嘛?那么就开始喽~

    AOP(Aspect Oriented Programming):面向切面编程,也是一种变成思想。(静态角度)

    OOP(Object Oriented Programming):面向对象编程。(动态代理:JDK动态代理    CGLIB动态代理)

    代理模(Proxy):为其他对象提供一个代理以控制对这个对象的访问。

    适合的场合:远程代理  虚拟代理  安全代理(只需要简单了解不做详解)

                                                          ↑   ↑   ↑   ↑   ↑   ↑只是关于代理的图片展示稍后会有详细代码

    基本术语(一些名词): 

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

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

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

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

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

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

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

    Spring的经典AOP配置方案

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

      2、注解配置的AOP

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

    接下来进入代码模式:

    代码模式一:纯POJO(通过POJO来实现一个前置增强类)

    定义一个简单的UserBiz类给它一个方法:

    1 package cn.happy.biz;
    2 
    3 public class UserBiz {
    4    public void addStu(UserInf user){
    5        System.out.println("add  ok");
    6    }
    7 }

    在aop包下BeforeAdvice前置增强类,它需要实现MethodBeforeAdvice接口的before方法:

     1 import org.springframework.aop.MethodBeforeAdvice;
     2 
     3 /**
     4  * before
     5  *
     6  */
     7 public class BeforeAdvice implements MethodBeforeAdvice{
     8 
     9     /**
    10      * 
    11      * @param method 被代理的目标的方法
    12      * @param args  传递给目标方法的参数
    13      * @param obj    被代理的目标对象
    14  
    15      * @throws Throwable
    16      */
    17     @Override
    18     public void before(Method method, Object[] args , Object obj)
    19             throws Throwable {
    20         System.out.println("========before======");
    21     }

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

     1 ......
     2   <bean id="biz" class="cn.happy.biz.UserBiz"></bean>
     3    
     4    <!-- 前置 -->
     5    <bean id="beforeAdvice" class="cn.happy.aop.BeforeAdvice"></bean>
     6    <!-- aop配置切面 -->
     7    <aop:config>
     8    <!-- 定义切点 -->
     9    <aop:pointcut expression="execution(public void *(cn.happy.biz.UserInf))"      id="pointcut"/>
    10    <!-- 增强处理和切点结合 -->
    11    <aop:advisor advice-ref="beforeAdvice" pointcut-ref="pointcut"/>
    12    <aop:advisor advice-ref="afterAdivice" pointcut-ref="pointcut"/>
    13    </aop:config>
    14 ......

    测试类:

    1  public void testOne(){
    2         ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
    3         UserBiz biz = (UserBiz)ctx.getBean("biz");
    4         biz.addStu(new UserInf());
    5         
    6     }

    =========================华丽的分割线==================================

    用注解配置的AOP:前置通知,后置通知,返回通知,异常通知,环绕通知

    定义一个接口:

    1 public interface ISomeService {
    2     //1.1  执行事务
    3    public void doTransaction();
    4     //1.2 书写日志
    5    public String doLog();
    6 }

    实现接口的实现类:

     1 public class SomeServiceImpl implements ISomeService {
     2 
     3     public void doTransaction() {
     4         System.out.println("开启事务");
     5     }
     6 
     7     public String doLog() {
     8         System.out.println("书写日志"+5/0);
     9         return "我是书写日志的返回值哦!!!!!";
    10     }
    11 
    12 }

    增强类用注解写:

     1 @Aspect
     2 public class MyAspect {
     3     //前置通知
     4     @Before(value="execution(public * *(..))")
     5     public void MyBefore(){
     6         System.out.println("这是前置通知哦!!!!!!!在执行目标对象之前执行");
     7     }
     8     
     9     //后置通知
    10     @AfterReturning(value="execution(public * *(..))")
    11     public void MyAfterReturning(){
    12         System.out.println("这是后置通知哦!!!!!!!在执行目标对象之前执行");
    13     }
    14     
    15     //环绕通知
    16 /*    @Around(value="execution(public * *(..))")
    17     public void MyAround(ProceedingJoinPoint pjp){
    18         System.out.println("这是环绕通知前哦!!!!!!!在执行目标对象之前执行");
    19         try {
    20             pjp.proceed();
    21             System.out.println("这是环绕通知后哦!!!!!!!在执行目标对象之前执行");
    22         } catch (Throwable e) {
    23             // TODO Auto-generated catch block
    24             e.printStackTrace();
    25         }
    26     }*/
    27     
    28     //异常通知
    29     @AfterThrowing(value="execution(public * *(..))")
    30     public void MyAfterThrowing(){
    31         System.out.println("这是异常通知哦!!!!!!!在执行目标对象之前执行");
    32     }
    33     
    34     //最终通知
    35     @After(value="execution(public * *(..))")
    36     public void MyAfter(){
    37         System.out.println("这是最终通知哦!!!!!!!在执行目标对象之前执行");
    38     }
    39 }

     

    配置文件:

    1 <!-- 目标对象 -->
    2    <bean id="someService" class="cn.happy.enetity.SomeServiceImpl"></bean>
    3 
    4    <!-- 切面: -->
    5    <bean id="myAspect" class="cn.happy.aspece.MyAspect"></bean>
    6    <!--aop:aspectj可以启动对@AspectJ注解支持-->
    7    <aop:aspectj-autoproxy/>
    8 </beans>

    测试类:

    1 public void testOne(){
    2         
    3         ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
    4         ISomeService service = (ISomeService)ctx.getBean("someService");
    5         service.doTransaction();
    6         String result = service.doLog();
    7         System.out.println(result);
    8     }

    =========================华丽的分割线==================================

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

    定义一个接口:

    1 public interface ISomeService {
    2     //1.1  执行事务
    3    public void doTransaction();
    4     //1.2 书写日志
    5    public String doLog();
    6 }
    

      

    实现类:

     1 public class SomeServiceImpl implements ISomeService {
     2 
     3     public void doTransaction() {
     4         System.out.println("开启事务");
     5     }
     6 
     7     public String doLog() {
     8         /*System.out.println("书写日志"+5/0);*/
     9         System.out.println("书写日志");
    10         return "我是书写日志的返回值哦!!!!!";
    11     }
    12 
    13 }

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

     1 public class MyAspect {
     2     // 前置通知execution(public * *(..))
     3     public void MyBefore() {
     4         System.out.println("这是前置通知哦!!!!!!!在执行目标对象之前执行");
     5     }
     6 
     7     // 后置通知execution(public * *(..))
     8     public void MyAfterReturning() {
     9         System.out.println("这是后置通知哦!!!!!!!在执行目标对象之前执行");
    10     }
    11 
    12     // 异常通知
    13     public void MyAfterThrowing() {
    14         System.out.println("这是异常通知哦!!!!!!!在执行目标对象之前执行");
    15     }
    16 
    17     // 最终通知
    18     public void MyAfter() {
    19         System.out.println("这是最终通知哦!!!!!!!在执行目标对象之前执行");
    20     }
    21     
    22     //环绕通知
    23     public String MyAround(ProceedingJoinPoint pjp){
    24         System.out.println("这是环绕通知前哦!!!!!!!在执行目标对象之前执行");
    25         try {
    26             Object result=pjp.proceed();
    27             System.out.println("这是环绕通知后哦!!!!!!!在执行目标对象之前执行");
    28         } catch (Throwable e) {
    29             // TODO Auto-generated catch block
    30             e.printStackTrace();
    31         }
    32         return "result";
    33     }
    34 }

     配置文件:

     1 ......
     2  <!-- 目标对象 -->
     3    <bean id="someService" class="enetity.SomeServiceImpl"></bean>
     4 
     5    <!-- 切面: -->
     6    <bean id="myAspect" class="aspece.MyAspect"></bean>
     7   
     8   
     9   <!--  aop的配置 -->
    10   <aop:config>
    11   <!-- 切点 -->
    12   <aop:pointcut expression="execution(public * *(..))" id="dopointcut"/>
    13       <aop:aspect ref="myAspect">
    14   
    15           <aop:before method="MyBefore" pointcut-ref="dopointcut"/>
    16           <aop:after-returning method="MyAfterReturning" pointcut-ref="dopointcut"/>
    17           <!-- <aop:after-throwing method="MyAfterThrowing" pointcut-ref="dopointcut"/> -->
    18           <aop:after method="MyAfter" pointcut-ref="dopointcut"/>
    19           <aop:around method="MyAround" pointcut-ref="dopointcut"/>
    20       </aop:aspect>
    21   
    22   </aop:config>
    23 </beans>
    24 ......

    测试类:

    1   public void testOne(){
    2         
    3         ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
    4         ISomeService service = (ISomeService)ctx.getBean("someService");
    5         service.doTransaction();
    6         String result = service.doLog();
    7         System.out.println(result);
    8     }

    以上就是我对AOP相关知识代码层面的讲解。学的不是很好,也是早上请教了同学才能更深一层了解AOP。就如文章开头:

      “自立”是自然对每个人的要求.也许你的父母、老师能够帮助你,其他人也可以帮助你,但是所有这些人都只是帮你更加自主、自立。

    希望可以鼓励那些在快学不下去的时候去请教下同学,老师...

      

      

      

  • 相关阅读:
    迷宫广搜
    通过地址获取百度地图经纬度
    图片上传存储数据库
    spring boot加载配置文件的顺序
    阿里 短信认证
    spring boot properties文件与yaml文件的区别
    springboot pom问题及注解
    手机短信认证
    获取class对象的三种方法以及通过Class对象获取某个类中变量,方法,访问成员
    关于mysql优化问题
  • 原文地址:https://www.cnblogs.com/ay-nzz/p/by_dzz.html
Copyright © 2020-2023  润新知