Spring之@Aspect中通知的5种方式详解

目录
  • @Before:前置通知
    • 案例
    • 对应的通知类
  • 通知中获取被调方法信息
    • JoinPoint:连接点信息
    • ProceedingJoinPoint:环绕通知连接点信息
    • Signature:连接点签名信息
  • @Around:环绕通知
    • 介绍
    • 特点
    • 案例
    • 对应的通知类
  • @After:后置通知
    • 介绍
    • 特点
    • 对应的通知类
  • @AfterReturning:返回通知
    • 用法
    • 特点
    • 案例
    • 对应的通知类
  • @AfterThrowing:异常通知
    • 用法
    • 特点
    • 案例
    • 对应的通知类
  • 几种通知对比

@Aspect中有5种通知

  • @Before:前置通知, 在方法执行之前执行
  • @Aroud:环绕通知, 围绕着方法执行
  • @After:后置通知, 在方法执行之后执行
  • @AfterReturning:返回通知, 在方法返回结果之后执行
  • @AfterThrowing:异常通知, 在方法抛出异常之后

这几种通知用起来都比较简单,都是通过注解的方式,将这些注解标注在@Aspect类的方法上,这些方法就会对目标方法进行拦截,下面我们一个个来看一下。

@Before:前置通知

介绍

定义一个前置通知

@Aspect
public class BeforeAspect {

    @Before("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void before(JoinPoint joinPoint) {
        System.out.println("我是前置通知!");
    }
}
  • 类上需要使用@Aspect标注
  • 任意方法上使用@Before标注,将这个方法作为前置通知,目标方法被调用之前,会自动回调这个方法
  • @Before标注的方法参数可以为空,或者为JoinPoint类型,当为JoinPoint类型时,必须为第一个参数
  • @Before标注的方法名称可以随意命名,符合java规范就可以,其他通知也类似

@Before中value的值为切入点表达式,也可以采用引用的方式指定切入点,如:

package com.javacode2018.aop.demo10.test1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class BeforeAspect {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @Before("com.javacode2018.aop.demo10.test1.BeforeAspect.pc()")
    public void before(JoinPoint joinPoint) {
        System.out.println("我是前置通知!");
    }
}

此时,before方法上面的切入引用了pc方法上面的@Pointcut的值

案例

来个普通的service

package com.javacode2018.aop.demo10.test1;

public class Service1 {
    public String say(String name) {
        return "你好:" + name;
    }

    public String work(String name) {
        return "开始工作了:" + name;
    }
}

给上面的类定义一个前置通知,Service1中的所有方法执行执行,输出一段文字我是前置通知!

package com.javacode2018.aop.demo10.test1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class BeforeAspect1 {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @Before("com.javacode2018.aop.demo10.test1.BeforeAspect1.pc()")
    public void before(JoinPoint joinPoint) {
        System.out.println("我是前置通知!");
    }
}

测试代码

package com.javacode2018.aop.demo10;

import com.javacode2018.aop.demo10.test1.BeforeAspect1;
import com.javacode2018.aop.demo10.test1.Service1;
import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;

public class AopTest10 {

    @Test
    public void test1() {
        Service1 target = new Service1();
        Class<BeforeAspect1> aspectClass = BeforeAspect1.class;
        AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.addAspect(aspectClass);
        Service1 proxy = proxyFactory.getProxy();
        System.out.println(proxy.say("路人"));
        System.out.println(proxy.work("路人"));
    }
}

运行输出

我是前置通知!
你好:路人
我是前置通知!
开始工作了:路人

对应的通知类

@Before通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJMethodBeforeAdvice

通知中获取被调方法信息

通知中如果想获取被调用方法的信息,分2种情况

  • 非环绕通知,可以将org.aspectj.lang.JoinPoint作为通知方法的第1个参数,通过这个参数获取被调用方法的信息
  • 如果是环绕通知,可以将org.aspectj.lang.ProceedingJoinPoint作为方法的第1个参数,通过这个参数获取被调用方法的信息

JoinPoint:连接点信息

org.aspectj.lang.JoinPoint

提供访问当前被通知方法的目标对象、代理对象、方法参数等数据:

package org.aspectj.lang;
import org.aspectj.lang.reflect.SourceLocation;

public interface JoinPoint {
    String toString();         //连接点所在位置的相关信息
    String toShortString();     //连接点所在位置的简短相关信息
    String toLongString();     //连接点所在位置的全部相关信息
    Object getThis();         //返回AOP代理对象
    Object getTarget();       //返回目标对象
    Object[] getArgs();       //返回被通知方法参数列表,也就是目前调用目标方法传入的参数
    Signature getSignature();  //返回当前连接点签名,这个可以用来获取目标方法的详细信息,如方法Method对象等
    SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
    String getKind();        //连接点类型
    StaticPart getStaticPart(); //返回连接点静态部分
} 

ProceedingJoinPoint:环绕通知连接点信息

用于环绕通知,内部主要关注2个方法,一个有参的,一个无参的,用来继续执行拦截器链上的下一个通知。

package org.aspectj.lang;
import org.aspectj.runtime.internal.AroundClosure;

public interface ProceedingJoinPoint extends JoinPoint {

    /**
     * 继续执行下一个通知或者目标方法的调用
     */
    public Object proceed() throws Throwable;

    /**
     * 继续执行下一个通知或者目标方法的调用
     */
    public Object proceed(Object[] args) throws Throwable;

}

Signature:连接点签名信息

注意JoinPoint#getSignature()这个方法,用来获取连接点的签名信息,这个比较重要

Signature getSignature();

通常情况,spring中的aop都是用来对方法进行拦截,所以通常情况下连接点都是一个具体的方法,Signature有个子接口

org.aspectj.lang.reflect.MethodSignature

JoinPoint#getSignature()都可以转换转换为MethodSignature类型,然后可以通过这个接口提供的一些方法来获取被调用的方法的详细信息。

下面对上面的前置通知的案例改造一下,获取被调用方法的详细信息,新建一个Aspect类:BeforeAspect2

package com.javacode2018.aop.demo10.test2;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;

@Aspect
public class BeforeAspect2 {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @Before("com.javacode2018.aop.demo10.test2.BeforeAspect2.pc()")
    public void before(JoinPoint joinPoint) {
        //获取连接点签名
        Signature signature = joinPoint.getSignature();
        //将其转换为方法签名
        MethodSignature methodSignature = (MethodSignature) signature;
        //通过方法签名获取被调用的目标方法
        Method method = methodSignature.getMethod();
        //输出方法信息
        System.out.println(method);
    }
}

测试用例

@Test
public void test2() {
    Service1 target = new Service1();
    Class<BeforeAspect2> aspectClass = BeforeAspect2.class;
    AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
    proxyFactory.setTarget(target);
    proxyFactory.addAspect(aspectClass);
    Service1 proxy = proxyFactory.getProxy();
    System.out.println(proxy.say("路人"));
    System.out.println(proxy.work("路人"));
}

运行输出

public java.lang.String com.javacode2018.aop.demo10.test1.Service1.say(java.lang.String)
你好:路人
public java.lang.String com.javacode2018.aop.demo10.test1.Service1.work(java.lang.String)
开始工作了:路人

@Around:环绕通知

介绍

环绕通知会包裹目标目标方法的执行,可以在通知内部调用ProceedingJoinPoint.process方法继续执行下一个拦截器。

用起来和@Before类似,但是有2点不一样

若需要获取目标方法的信息,需要将ProceedingJoinPoint作为第一个参数

通常使用Object类型作为方法的返回值,返回值也可以为void

特点

环绕通知比较特殊,其他4种类型的通知都可以用环绕通知来实现。

案例

通过环绕通知来统计方法的耗时。

package com.javacode2018.aop.demo10.test3;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;

@Aspect
public class AroundAspect3 {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @Around("com.javacode2018.aop.demo10.test3.AroundAspect3.pc()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取连接点签名
        Signature signature = joinPoint.getSignature();
        //将其转换为方法签名
        MethodSignature methodSignature = (MethodSignature) signature;
        //通过方法签名获取被调用的目标方法
        Method method = methodSignature.getMethod();

        long startTime = System.nanoTime();
        //调用proceed方法,继续调用下一个通知
        Object returnVal = joinPoint.proceed();
        long endTime = System.nanoTime();
        long costTime = endTime - startTime;
        //输出方法信息
        System.out.println(String.format("%s,耗时(纳秒):%s", method.toString(), costTime));
        //返回方法的返回值
        return returnVal;
    }
}

测试用例

@Test
public void test3() {
    Service1 target = new Service1();
    Class<AroundAspect3> aspectClass = AroundAspect3.class;
    AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
    proxyFactory.setTarget(target);
    proxyFactory.addAspect(aspectClass);
    Service1 proxy = proxyFactory.getProxy();
    System.out.println(proxy.say("路人"));
    System.out.println(proxy.work("路人"));
}

运行输出

public java.lang.String com.javacode2018.aop.demo10.test1.Service1.say(java.lang.String),耗时(纳秒):19000500
你好:路人
public java.lang.String com.javacode2018.aop.demo10.test1.Service1.work(java.lang.String),耗时(纳秒):59600
开始工作了:路人

对应的通知类

@Around通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJAroundAdvice

@After:后置通知

介绍

后置通知,在方法执行之后执行,用法和前置通知类似。

特点

  • 不管目标方法是否有异常,后置通知都会执行
  • 这种通知无法获取方法返回值
  • 可以使用JoinPoint作为方法的第一个参数,用来获取连接点的信息

案例

Service1中任意方法执行完毕之后,输出一行日志。

package com.javacode2018.aop.demo10.test4;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class AfterAspect4 {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @After("com.javacode2018.aop.demo10.test4.AfterAspect4.pc()")
    public void after(JoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        System.out.println(String.format("%s,执行完毕!", methodSignature.getMethod()));
    }
}

测试案例

@Test
public void test4() {
    Service1 target = new Service1();
    Class<AfterAspect4> aspectClass = AfterAspect4.class;
    AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
    proxyFactory.setTarget(target);
    proxyFactory.addAspect(aspectClass);
    Service1 proxy = proxyFactory.getProxy();
    System.out.println(proxy.say("路人"));
    System.out.println(proxy.work("路人"));
}

运行输出

public java.lang.String com.javacode2018.aop.demo10.test1.Service1.say(java.lang.String),执行完毕!
你好:路人
public java.lang.String com.javacode2018.aop.demo10.test1.Service1.work(java.lang.String),执行完毕!
开始工作了:路人

对应的通知类

@After通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJAfterAdvice

这个类中有invoke方法,这个方法内部会调用被通知的方法,其内部采用try..finally的方式实现的,所以不管目标方法是否有异常,通知一定会被执行。

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        //继续执行下一个拦截器
        return mi.proceed();
    }
    finally {
        //内部通过反射调用被@After标注的方法
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
}

@AfterReturning:返回通知

用法

返回通知,在方法返回结果之后执行。

特点

  • 可以获取到方法的返回值
  • 当目标方法返回异常的时候,这个通知不会被调用,这点和@After通知是有区别的

案例

后置通知中打印出方法及返回值信息。

package com.javacode2018.aop.demo10.test5;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class AfterReturningAspect5 {
    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @AfterReturning(value = "com.javacode2018.aop.demo10.test5.AfterReturningAspect5.pc()", returning = "retVal")
    public void afterReturning(JoinPoint joinPoint, Object retVal) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        System.out.println(String.format("%s返回值:%s", methodSignature.getMethod(), retVal));
    }

}

注意@AfterReturning注解,用到了2个参数

  • value:用来指定切入点
  • returning:用来指定返回值对应方法的参数名称,返回值对应方法的第二个参数,名称为retVal

对应的通知类

@AfterReturning通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJAfterReturningAdvice

@AfterThrowing:异常通知

用法

在方法抛出异常之后会回调@AfterThrowing标注的方法。

@AfterThrowing标注的方法可以指定异常的类型,当被调用的方法触发该异常及其子类型的异常之后,会触发异常方法的回调。也可以不指定异常类型,此时会匹配所有异常。

未指定异常类型

未指定异常类型,可以匹配所有异常类型,如下

@AfterThrowing(value = "切入点")
public void afterThrowing()

指定异常类型

通过@AfterThrowingthrowing指定参数异常参数名称,我们用方法的第二个参数用来接收异常,第二个参数名称为e,下面的代码,当目标方法发生IllegalArgumentException异常及其子类型异常时,下面的方法会被回调。

@AfterThrowing(value = "com.javacode2018.aop.demo10.test6.AfterThrowingAspect6.pc()", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, IllegalArgumentException e)

特点

不论异常是否被异常通知捕获,异常还会继续向外抛出。

案例

Service1中加了login方法,用户名不是路人甲java时抛出异常。

package com.javacode2018.aop.demo10.test1;

public class Service1 {
    public String say(String name) {
        return "你好:" + name;
    }

    public String work(String name) {
        return "开始工作了:" + name;
    }

    public boolean login(String name) {
        if (!"路人甲java".equals(name)) {
            throw new IllegalArgumentException("非法访问!");
        }
        return true;
    }
}

来个异常通知

package com.javacode2018.aop.demo10.test6;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class AfterThrowingAspect6 {
    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @AfterThrowing(value = "com.javacode2018.aop.demo10.test6.AfterThrowingAspect6.pc()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, IllegalArgumentException e) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        System.out.println(String.format("%s发生异常,异常信息:%s", methodSignature.getMethod(), e.getMessage()));
    }

}

测试用例

@Test
public void test6() {
    Service1 target = new Service1();
    Class<AfterThrowingAspect6> aspectClass = AfterThrowingAspect6.class;
    AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
    proxyFactory.setTarget(target);
    proxyFactory.addAspect(aspectClass);
    Service1 proxy = proxyFactory.getProxy();
    proxy.login("路人");
}

运行输出

public boolean com.javacode2018.aop.demo10.test1.Service1.login(java.lang.String)发生异常,异常信息:非法访问!
 
java.lang.IllegalArgumentException: 非法访问!
 
 at com.javacode2018.aop.demo10.test1.Service1.login(Service1.java:14)
 at com.javacode2018.aop.demo10.test1.Service1$$FastClassBySpringCGLIB$$ea03ccbe.invoke(<generated>)
 at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
 at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)

对应的通知类

@AfterThrowing通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJAfterThrowingAdvice

来看一下这个类的invoke方法,这个方法是关键

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        //继续调用下一个拦截器链
        return mi.proceed();
    }
    catch (Throwable ex) {
        //判断ex和需要不糊的异常是否匹配
        if (shouldInvokeOnThrowing(ex)) {
            //通过反射调用@AfterThrowing标注的方法
            invokeAdviceMethod(getJoinPointMatch(), null, ex);
        }
        //继续向外抛出异常
        throw ex;
    }
}

几种通知对比

通知类型 执行时间点 可获取返回值 目标方法异常时是否会执行
@Before 方法执行之前
@Around 环绕方法执行 自己控制
@After 方法执行后
@AfterReturning 方法执行后
@AfterThrowing 方法发生异常后

到此这篇关于Spring之@Aspect中通知的5种方式详解的文章就介绍到这了,更多相关Spring @Aspect通知内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 谈谈Spring AOP中@Aspect的高级用法示例

    前言 本文主要跟大家分享介绍了关于Spring AOP中@Aspect的高级用法,下面话不多说了,来随着小编一起看看详细的介绍吧. 1 切点复合运算 支持在切点定义中加入以下运算符进行复合运算: 运算符 说明 && 与运算. ! 非运算. || 或运算. 2 切点命名 一般情况下,切点是直接声明在需要增强方法处,这种切点的声明方式称为匿名切点,匿名切点只能在声明处被使用 . 如果希望在其它地方可以重用这个切点,我们可以通过 @Pointcut 注解及切面类方法来命名它. public cl

  • Spring-AOP @AspectJ进阶之如何绑定代理对象

    概述 使用this()或target()可绑定被代理对象实例,在通过类实例名绑定对象时,还依然具有原来连接点匹配的功能,只不过类名是通过增强方法中同名入参的类型间接决定罢了. 这里我们通过this()来了解对象绑定的用法: 实例 代码已托管到Github-> https://github.com/yangshangwei/SpringMaster 业务类 package com.xgj.aop.spring.advisor.aspectJAdvance.bindProxyObj; import

  • Spring声明式事务和@Aspect的拦截顺序问题的解决

    在使用AbstractRoutingDataSource配置多数据源时,发现使用@aspect配置的DataSourceSwitchAspect总是在声明式事务之后执行,配置了Order依然不行,经过调研发现是由于两者的aop代理方式不一致导致. 在spring内部,是通过BeanPostProcessor(<spring 攻略>一书中翻译为,后处理器)来完成自动创建代理工作的.根据匹配规则的不同大致分为三种类别: 1.匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameA

  • 基于Spring AOP @AspectJ进阶说明

    @AspectJ可以使用切点函数定义切点,我们还可以使用逻辑运算符对切点进行复核运算得到复合的切点,为了在切面中重用切点,我们还可以对切点进行命名,以便在其他的地方引用定义过的切点. 当一个连接点匹配多个切点时,需要考虑织入顺序的问题,此外一个重要的问题是如何再增强中访问连接点上下文的信息. Waiter接口: package com.yyq.aspectJAdvanced; public interface Waiter { void greetTo(String name); void se

  • 在Spring 中使用@Aspect 控制自定义注解的操作

    Spring 中使用@Aspect 控制自定义注解 看这篇介绍@Aspect 1.定义系统日志注解类 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SysLog { String value() default ""; } 2.定义切面处理类 package com.kxs.common.aspect; import com.google.gso

  • 基于spring@aspect注解的aop实现过程代码实例

    @AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格.通过在你的基于架构的 XML 配置文件中包含以下元素,@AspectJ 支持是可用的. 第一步:编写切面类 package com.dascom.hawk.app.web.tool; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.l

  • Spring之@Aspect中通知的5种方式详解

    目录 @Before:前置通知 案例 对应的通知类 通知中获取被调方法信息 JoinPoint:连接点信息 ProceedingJoinPoint:环绕通知连接点信息 Signature:连接点签名信息 @Around:环绕通知 介绍 特点 案例 对应的通知类 @After:后置通知 介绍 特点 对应的通知类 @AfterReturning:返回通知 用法 特点 案例 对应的通知类 @AfterThrowing:异常通知 用法 特点 案例 对应的通知类 几种通知对比 @Aspect中有5种通知

  • Node.js中参数传递的两种方式详解

    目录 参数传递方式 GET方式 POST方式 动态网页 参数传递方式 在Node.js中,参数传递常见的共两种方式: GET方式:通过地址栏键=值的方式进行传递. POST方式:通过表单的方式传递请求数据. GET方式 GET方式通常是在请求地址中以[?参数1=值1&参数2=值2]的格式进行传递,在Node.js中可以通过获取url然后进行获取参数,如下所示: //1.引入http模块 var http = require('http'); //2.创建服务 var server = http.

  • Spring boot实现热部署的两种方式详解

    热部署是什么 大家都知道在项目开发过程中,常常会改动页面数据或者修改数据结构,为了显示改动效果,往往需要重启应用查看改变效果,其实就是重新编译生成了新的 Class 文件,这个文件里记录着和代码等对应的各种信息,然后 Class 文件将被虚拟机的 ClassLoader 加载. 而热部署正是利用了这个特点,它监听到如果有 Class 文件改动了,就会创建一个新的 ClaassLoader 进行加载该文件,经过一系列的过程,最终将结果呈现在我们眼前. 类加载机制 Java 中的类经过编译器可以把代

  • Spring框架实现AOP的两种方式详解

    目录 第一种AOP实现方式 AfterLog Log 配置文件 实例调用 定义接口 第二种AOP实现方式 第一种AOP实现方式 AfterLog package com.xxx.demo.service1; import org.junit.After; import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; public class AfterLog implements Aft

  • Spring为IOC容器注入Bean的五种方式详解

    这篇文章主要介绍了Spring为IOC容器注入Bean的五种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 @Import导入组件,id默认是组件的全类名 //类中组件统一设置.满足当前条件,这个类中配置的所有bean注册才能生效: @Conditional({WindowsCondition.class}) @Configuration @Import({Color.class,Red.class,MyImportSelector

  • Spring实例化bean的四种方式详解

    目录 一.bean实例化——构造方法(常用) 二.bean实例化——静态工厂(了解) 三.bean实例化——实例工厂(了解) 四.bean实例化——FactoryBean(实用) 一.bean实例化——构造方法(常用) bean本质上就是对象,创建bean使用构造方法完成 BookDao接口: public interface BookDao { public void save(); } BookDaoImpl实现类,利用构造方式提供可访问的构造方法,输出相应字符串: import com.i

  • Spring Bean属性注入的两种方式详解

    目录 属性注入概念 一.构造器注入 示例1 注意点 二.setter注入 示例2 三.如何选择注入方式 属性注入概念 Spring 属性注入(DI依赖注入)有两种方式:setter注入,构造器注入. 这个注入的属性可以是普通属性(基本数据类型与String等),也可以是一个引用数据类型(主要是对象),或者是一个集合(list.map.set等) 下表是属性注入bean标签中常用的元素 元素名称 描述 constructor-arg 构造器注入.该元素的 index 属性指定构造参数的索引(从 0

  • jquery 中toggle的2种用法详解(推荐)

    一.在元素的click事件中绑定两个或两个以上的函数  toggle不像bind需要在后面添加"click"来绑定click触发事件,toggle本身就是click触发的(而且只能click触发), 如下实例: <input id="btntest" type="button" value="点一下我" /> <div>我是动态显示的</div> <script type="

  • Java中遍历ConcurrentHashMap的四种方式详解

    这篇文章主要介绍了Java中遍历ConcurrentHashMap的四种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 方式一:在for-each循环中使用entries来遍历 System.out.println("方式一:在for-each循环中使用entries来遍历");for (Map.Entry<String, String> entry: map.entrySet()) { System.out.pr

  • Spring Boot项目中定制拦截器的方法详解

    这篇文章主要介绍了Spring Boot项目中定制拦截器的方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Servlet 过滤器属于Servlet API,和Spring关系不大.除了使用过滤器包装web请求,Spring MVC还提供HandlerInterceptor(拦截器)工具.根据文档,HandlerInterceptor的功能跟过滤器类似,但拦截器提供更精细的控制能力:在request被响应之前.request被响应之后.视

随机推荐