欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SSM学习—Spring(第六天学习记录)

程序员文章站 2022-06-06 13:59:22
...

Aop

  • AOP(Aspect-Oriented Programming,面向切面编程):是一种新的方法论,是对传统OOP(Object-Oriented Programming,面向对象编程)的补充。
  • AOP编程操作的主要对象是切面(aspect),而切面模块化横切关注点(可以把切面当做一个有特殊功能的类)
  • 在应用AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能应用在哪里,以什么方式应用,并且不必修改受影响的类。这样一来横切关注点就被模块化到特殊的类里——这样的类我们通常称之为“切面”
    SSM学习—Spring(第六天学习记录)

专业名词

  1. 横切关注点
    从每个方法中抽取出来的同一类非核心业务。(例如上图的日志)
  2. 切面(Aspect)
    封装横切关注点信息的类,每个关注点体现为一个通知方法。
  3. 通知(Advice)
    切面必须要完成的各个具体工作
  4. 目标(Target)
    被通知的对象
  5. 代理(Proxy)
    向目标对象应用通知之后创建的代理对象
  6. 连接点(Joinpoint)
    横切关注点在程序代码中的具体体现,对应程序执行的某个特定位置。例如:类某个方法调用前、调用后、方法捕获到异常后等。
    在应用程序中可以使用横纵两个坐标来定位一个具体的连接点:

SSM学习—Spring(第六天学习记录)
7. 切入点(pointcut):
定位连接点的方式。每个类的方法中都包含多个连接点,所以连接点是类中客观存在的事物。如果把连接点看作数据库中的记录,那么切入点就是查询条件——AOP可以通过切入点定位到特定的连接点。切点通过org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。

SSM学习—Spring(第六天学习记录)

细节

切入点表达式:通过表达式去定位一个或多个具体的连接
	语法格式:execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名]([参数列表]))

SSM学习—Spring(第六天学习记录)

当前连接点所在方法的方法名、当前传入的参数值等等。这些信息都封装在JoinPoint接口的实例对象中	

SSM学习—Spring(第六天学习记录)

	@Component      //先标示为组件,交给IOC容器管理
@Aspect         //标识为切面
@Order(2)
public class LoggingAspect {
    /**
     * 前置通知:在目标方法执行之前执行的方法
     * 注意导包的时候不要导错了
     * 切入点表达式
     * execution(public int Aspectj.Before.ArithmeticCalculatorimpl.add(int,int))
     *声明切入点表达式
     */
    @Pointcut("execution(* Aspectj.Before.*.*(..))")
    public void declarePointCut(){

    }
   // @Before("execution(public int Aspectj.Before.ArithmeticCalculatorimpl.add(int,int))")
    @Before("declarePointCut()")
    public void beforeMethod(JoinPoint joinPoint){
        Object args[]=joinPoint.getArgs();
        System.out.println("前置通知:"+ Arrays.asList(args));
    }
    /**
     * 后置通知:在目标方法之后执行,不管目标方法有没有抛出异常
     *	  		*    * com.atguigu.spring.aspectJ.annotation.*.*(..)
	 *  	    * : 任意修饰符 任意返回值
	 *    		* : 任意类
	 *    		* : 任意方法
	 *    		..: 任意参数列表
	 *    
     */
    @After("execution(* Aspectj.Before.*.*(..))")
    public void AfterMethod(JoinPoint joinPoint){
        //方法的名字
        String methodName=joinPoint.getSignature().getName();
        System.out.println("后置通知:"+methodName);
    }
    /**
     * 返回通知:在目标方法正常执行结束之后执行,可以获取方法的返回值
     * 通过returning来制定一个名字,必须与方法里的形参一样
     */
    @AfterReturning(value="execution(* Aspectj.Before.*.*(..))",returning = "result")
    public void AfterReturnMethod(JoinPoint joinPoint,Object result){
        //方法的名字
        String methodName=joinPoint.getSignature().getName();
        System.out.println("返回通知:"+methodName+"返回结果"+result);
    }
    @AfterThrowing(value = "execution(* Aspectj.Before.*.*(..))",throwing = "ex")
    public void AfterThrowMethod(JoinPoint joinPoint,Exception ex){
        //方法的名字
        String methodName=joinPoint.getSignature().getName();
        System.out.println("异常通知:"+ex);
    }
    /**
     * 环绕通知:环绕着目标方法执行,可以理解为前置,后置,返回,异常的结合体更像是动态代理的过程
     */
    @Around(value = "execution(* Aspectj.Before.*.*(..))")
    public Object AroundMethod(ProceedingJoinPoint joinPoint){
        //执行目标放阿飞
       try {
           //前置
           Object obj=joinPoint.proceed();

           return obj;
            //返回
       }catch (Throwable e){
           e.printStackTrace();
       }finally {
           //后置
       }
        return null;
    }
}

Aspectj(Java社区里最完整的AOP框架)

所需jar包

com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar 
spring-aop-5.2.0.RELEASE.jar
spring-aspects-5.2.0.RELEASE.jar

命名空间

<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-4.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
	

重用切入点定义

1)在编写AspectJ切面时,可以直接在通知注解中书写切入点表达式。但同一个切点表达式可能会在多个通知中重复出现。
2)在AspectJ切面中,可以通过@Pointcut注解将一个切入点声明成简单的方法。切入点的方法体通常是空的,因为将切入点定义与应用程序逻辑混在一起是不合理的。
3)切入点方法的访问控制符同时也控制着这个切入点的可见性。如果切入点要在多个切面*用,最好将它们集中在一个公共的类中。在这种情况下,它们必须被声明为public。在引入这个切入点时,必须将类名也包括在内。如果类没有与这个切面放在同一个包中,还必须包含包名。
4)其他通知可以通过方法名称引入该切入点

代码实现:
	  @Pointcut("execution(* Aspectj.Before.*.*(..))")
    public void declarePointCut(){

    }
   // @Before("execution(public int Aspectj.Before.ArithmeticCalculatorimpl.add(int,int))")
    @Before("declarePointCut()")
在不同的文件里面调用
    //@Before("execution(* Aspectj.Before.*.*(..))")
    @Before("Aspectj.Before.LoggingAspect.declarePointCut()")

指定切面优先级

1)在同一个连接点上应用不止一个切面时,除非明确指定,否则它们的优先级是不确定的。
2)切面的优先级可以通过实现Ordered接口或利用@Order注解指定。
3)实现Ordered接口,getOrder()方法的返回值越小,优先级越高。

@Component
@Aspect
@Order(1)    //设置切面优先级,int类型的值,2147483647