初识aop和扩展aop

葉子。 葉子。     2022-08-08     534

关键词:

一、什么叫做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("书写日志"+5/0);
        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(面向切面编程)初识demo(代码片段)

刚学习了AOP的前值增强和后置增强,个人感觉就是在调用一些方法前,或调用一些方法后绑定一个方法,让这些方法被调用之前或者调用结束后执行这个方法。 例子:MyAdvice类:存放调用service方法前或后需要执行的方法:pub... 查看详情

spring框架初识

 1.AOP的相关概念   1.1AOP概述     1.1.1什么是AOP        AOP:全程是AspectOrientedProgramming即面向切面编程。是通过预编译方式和运行期动态代理实现程序功能的统一维护的... 查看详情

springioc和aop使用扩展

  Spring提供了设值注入,构造注入等依赖注入方式。  使用p命令空间可以简化属性注入的配置。  Spring提供的增强处理类型包括前置增强,异常抛出增强,环绕增强,最终增强等。  通过Schema形式将POJO的方法配置成切... 查看详情

spring繁华的aop王国---第五讲之应用案例和扩展

Spring繁华的AOP王国---第五讲之应用案例和扩展AOP应用案例异常处理java中的异常处理FaultBarrier安全检查缓存小结扩展篇嵌套方法拦截失效引出公开代理对象的话题原因解决方案Spring繁华的AOP王国—第一讲Spring繁华的AOP王国—第二... 查看详情

ioc和aop使用扩展。。。

实现依赖的多种方式。1.理解构造注入。2.掌握使用p命名空间实现属性注入。3.理解不同的数据类型的注入方式。4.如何通过构造注入为业务类注入所依赖的数据访问层对象,实现保存用户数据功能。5.创建带参构造方法。一个<... 查看详情

ioc和aop使用扩展

1.多种方式实现依赖注入Spring通过setter访问器实现了对属性的赋值,称为设值注入Spring还提供了通过构造方法赋值的能力,称为构造注入    两种注入方式的比较Setter注入:对于习惯了传统javabean开发的程序员,通过setter方... 查看详情

ioc和aop使用扩展多种方式实现依赖注入

  多种方式实现依赖注入  1.Spring使用setter访问器实现对属性的赋值,  2.Spring 构造constructor方法赋值,  3.接口注入  4.SpringP命名空间注入直接量    setter访问器实现方式following 实体类中设置属性的s... 查看详情

springaop由浅入深学习教程新手向

初识AOP(传统程序)Tips:如果想要快速查阅的朋友,可以直接跳转到初识AOP(Spring程序)这一大节(一)AOP术语(二)AOP入门案例:XML、注解方式(三)完全基于Spring的事务控制:XML、注解方式、纯注解方式(一)AOP的简单分析介绍在软件... 查看详情

day643.ioc和aop是扩展的核心-java业务开发常见错误(代码片段)

IoC和AOP是扩展的核心Hello,阿昌来也!今天记录的是IOC&AOP的一些基础内容案例的学习笔记。熟悉Java的都知道,Spring的家族庞大,常用的模块就有SpringData、SpringSecurity、SpringBoot、SpringCloud等。其实呢,Spring体系虽... 查看详情

初识spring

Spring是一个开源框架,为简化企业级应用开发而生,使用Spring可以使简单的JavaBean实现以前只有EJB才能实现的功能,Spring是一个IOC(DI)和AOP容器框架。轻量级(Spring是非侵入性的,基于Spring开发的应用中的对象可以不依赖与Spring中... 查看详情

aop横行切面编程和纵向编程介绍

 1aop:面向切面(方面)编程,扩展功能不修改源代码实现2AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码3aop底层使用动态代理实现(1)第一种情况,有接口情况,使用动态代理创建接口实现类代理对象(2)第... 查看详情

springaop

...中的一些问题:*AOP解决OOP中遇到的一些问题.是OOP的延续和扩展.1.2 为什么学习AOP对程序进行增强:不修改源码的情况下.*AOP可以进行权限校验,日志记录,性能监控,事务控制.1.3 Spring的AOP的由来:AOP最早由AOP联盟的组织提出的,... 查看详情

spring框架aop使用扩展

一、什么是AOP  1、将复杂的需求分解出不同的方面,将散布在系统汇中的公共功能集中解决;  2、采用代理机制组装起来运行,再不改变原程序的基础上对代码段进行增强处理,增加新的功能;  3、默认采取的是JDK动态... 查看详情

一起学spring之注解和schema方式实现aop

...前,先了解一下AspectJ。AspectJ是一个面向切面的框架,它扩展了Java语言,定义了AOP语法,能够在编译时实现代码的注入。Spring通过集成ApsectJ实现了以注解方式定义通知类,大大减少了配置文件的工作量。本文主要讲解通过注解... 查看详情

spring入门系列代理模式和aop

...目标对象功能实现的基础上,增加额外的功能,从而达到扩展目标对象功能的效果。简言之,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式。静态代理这种代理方式需要代理对... 查看详情

aop是啥意思?

...收被代理的类,并且要求被代理的类必须实现一个接口。扩展资料AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ。而动态代理则以SpringAOP为代表,静态代理是编译期... 查看详情

aop注解

Ioc和Aop使用扩展DI注入(设置注入/构造注入/p命名注入)1.构造注入第一步(类1)  (类二)第二步:Xml文件 第三步:单测   3.(DI)注解1.(小案例)第一步:xml<?xmlversion="1.0" encoding="UTF-8"?><beans xmlns="http... 查看详情

spring-aop原理与应用

...中的一些问题:*AOP解决OOP中遇到的一些问题.是OOP的延续和扩展.AOP作用    对程序进行增强:不修改源码的情况下.    *AOP可以进行权限校验,日志记录,性能监控,事务控制.Spring的AOP的由来:   &nb... 查看详情