Spring AOP介绍和实战

11 篇文章 0 订阅
摘要:我们将看到关于Spring AOP的概念以及如何实现它。

Spring AOP:
面向切面的编程是一种编程范式,类似于面向对象编程.面向对象编程的关键单元是类,类似于AOP的关键单元是切面.切面支持诸如事务管理之类的关注点的模块化,它跨越多个类和类型。它也称为横切关注点。

什么 AOP?

它提供了在业务逻辑之前、之后或周围应用关注点的可插入方法。让我们在日志的帮助下理解。您已经在不同的类中放置了日志记录,但是出于某些原因,如果您现在想删除日志,您必须在所有类中进行更改,但是您可以通过使用方面轻松地解决这个问题。如果你想删除日志,你只需要拔掉那个方面的插头。

AOP 概念:
Aspect:方面是一个实现跨越不同类的关注点的类,比如日志。它只是一个名字.
Joint Point : 它是程序执行的一个点,例如方法的执行。在Spring AOP中,连接点总是表示方法执行。
Advice : 方面在特定连接点上采取的行动例如:在执行getEmployeeName()方法之前,put日志。这里,我们在建议之前使用。
Pointcut : 切入点是决定在匹配的连接点上执行建议的表达式。Spring默认使用AspectJ切入点表达式语言。
Target object : 这些是应用建议的对象。例如:有一个对象,您希望在连接点上应用日志记录。
AOP proxy : Spring将创建JDK动态代理,以便通过建议调用围绕目标对象创建代理类。
Weaving : 从目标对象创建代理对象的过程可以称为编织。
Types of Advices :建议是由方面在特定的连接点上采取的行动。
Before Advice: 它在连接点之前执行
After Returning Advice:它在一个关节点完成后执行,没有任何异常.
After Throwing Advice:如果方法通过抛出异常来执行.
After Advice: 它在一个连接点之后执行,而不考虑结果.

Around Advice:它在连接点之前和之后执行.

Spring AOP AspectJ Annotation Example

在这篇文章中,我们将看到Spring AOP AspectJ注释示例。

下面是AspectJ注释,我们将使用它来实现Spring AOP。

@Aspect :要声明一个类作为方面,用于创建通知的注释是:
@Before : @Before注解被用来创建前置通知.它在实际的方法执行之前执行(连接点)。
@AfterReturning: 这个注释用于创建返回通知.它在一个方法执行完成后执行,没有任何异常。
@AfterThrowing: 这个注释用于在抛出通知之后创建.如果方法通过抛出一个异常来执行。
@After : 这个注释用于在通知之后创建.它在方法执行之后执行,而不考虑结果。

@Around : 这个注释用于创建环绕通知.它在连接点之前和之后执行。

项目结构:


@Before  :

比方说你有一些业务逻辑类(BusinessLogic.java),你想在这个类的getBusinessLogic方法执行之前做日志记录

package com.micai.spring.aop;

/**
 * 描述:
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/6/11 17:30
 */
public class BusinessLogic {

    public void getBusinessLogic() {
        System.out.println("*****************");
        System.out.println("In Business Logic method");
        System.out.println("*****************");
    }
}

现在我们将创建aspect类

package com.micai.spring.aop;

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

/**
 * 描述:
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/6/11 17:31
 */
@Aspect
public class LoggingAspect {

    @Before("execution(* com.micai.spring.aop.BusinessLogic.getBusinessLogic(..))")
    public void loggingBeforeBusinessLogic(JoinPoint joinPoint) {
        System.out.println("loggingBeforeBusinessLogic() is running!");
        System.out.println("Before execution of method : " + joinPoint.getSignature().getName());
    }
}
execution(* com.micai.spring.aop.BusinessLogic.getBusinessLogic(。。))是切入点表达式。

在BusinessLogic类的getBusinessLogic方法之前,它表示方法的执行。

让我们在applicationContext.xml中对上述bean进行配置。

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

    <aop:aspectj-autoproxy />

    <bean id="businessLogic" class="com.micai.spring.aop.BusinessLogic"></bean>

    <!-- Aspect -->
    <bean id="logAspect" class="com.micai.spring.aop.LoggingAspect"/>


</beans>

创建名为SpringAOPMain的主类来执行应用程序

package com.micai.spring;

import com.micai.spring.aop.BusinessLogic;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 描述:
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/6/11 17:34
 */
public class SpringAOPMain {

    public static void main(String [] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        BusinessLogic businessLogic = (BusinessLogic) applicationContext.getBean("businessLogic");
        businessLogic.getBusinessLogic();

    }
}

当您运行在程序之上时,您将得到以下输出:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
loggingBeforeBusinessLogic() is running!
Before execution of method : getBusinessLogic
*****************
In Business Logic method
*****************

Process finished with exit code 0

@After:

我在LoggingAspect中替换@before方法。带有@after注释的java方法。该方法将在实际业务逻辑执行后执行,因此要执行LoggingAspect。java看起来是这样的。

package com.micai.spring.aop;

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

/**
 * 描述:
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/6/11 17:31
 */
@Aspect
public class LoggingAspect {

    @After("execution(* com.micai.spring.aop.BusinessLogic.getBusinessLogic(..))")
    public void loggingBeforeBusinessLogic(JoinPoint joinPoint) {
        System.out.println("loggingAfterBusinessLogic() is running!");
        System.out.println("After execution of method : " + joinPoint.getSignature().getName());
    }
}

当您运行SpringAOPMain。再一次,你将会得到低于输出:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
*****************
In Business Logic method
*****************
loggingAfterBusinessLogic() is running!
After execution of method : getBusinessLogic

Process finished with exit code 0

正如您在上面的输出中看到的,在getBusinessLogic方法之后执行的loggingAfterBusinessLogic方法

@AfterReturning:
我将@after替换为@AfterReturning在以上的LoggingAspect.java。这种方法将在实际业务逻辑的执行之后执行,但前提是它成功返回。

package com.micai.spring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * 描述:
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/6/11 17:31
 */
@Aspect
public class LoggingAspect {

    @AfterReturning("execution(* com.micai.spring.aop.BusinessLogic.getBusinessLogic(..))")
    public void loggingBeforeBusinessLogic(JoinPoint joinPoint) {
        System.out.println("loggingAfterReturningBusinessLogic() is running!");
        System.out.println("AfterReturning execution of method : " + joinPoint.getSignature().getName());
    }
}

当您运行SpringAOPMain。再一次,你将会得到低于输出:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
*****************
In Business Logic method
*****************
loggingAfterReturningBusinessLogic() is running!
AfterReturning execution of method : getBusinessLogic

Process finished with exit code 0
@AfterThrowing:
我们再添加一个方法@AfterThrowing 注解. 如果在getBusinessLogic方法中发生任何异常,它将执行。

LoggingAspect.java

package com.micai.spring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;

/**
 * 描述:
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/6/11 17:31
 */
@Aspect
public class LoggingAspect {

    @AfterReturning("execution(* com.micai.spring.aop.BusinessLogic.getBusinessLogic(..))")
    public void loggingBeforeBusinessLogic(JoinPoint joinPoint) {
        System.out.println("loggingAfterReturningBusinessLogic() is running!");
        System.out.println("AfterReturning execution of method : " + joinPoint.getSignature().getName());
    }

    @AfterThrowing("execution(* com.micai.spring.aop.BusinessLogic.getBusinessLogic(..))")
    public void loggingAfterBusinessLogicException(JoinPoint joinPoint) {
        System.out.println("Exception occurred in getBusinessLogic method");
    }
}

现在,从getBusinessLogic抛出RuntimeException来测试@after抛出异常。BusinessLogic.java

package com.micai.spring.aop;

/**
 * 描述:
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/6/11 17:30
 */
public class BusinessLogic {

    public void getBusinessLogic() {
        System.out.println("*****************");
        System.out.println("In Business Logic method");
        System.out.println("*****************");
        throw new RuntimeException();
    }
}

当您运行SpringAOPMain。java,您将得到以下输出:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Exception in thread "main" java.lang.RuntimeException
	at com.micai.spring.aop.BusinessLogic.getBusinessLogic(BusinessLogic.java:16)
	at com.micai.spring.aop.BusinessLogic$$FastClassBySpringCGLIB$$776ce13d.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
	at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
*****************
In Business Logic method
*****************
Exception occurred in getBusinessLogic method
	at com.micai.spring.aop.BusinessLogic$$EnhancerBySpringCGLIB$$9a54a68e.getBusinessLogic(<generated>)
	at com.micai.spring.SpringAOPMain.main(SpringAOPMain.java:19)

Process finished with exit code 1

正如您所看到的,loggingAfterBusinessLogicException被执行,因为在业务逻辑中有例外。

@Around:

@Around的方法将在业务逻辑执行之前和之后被调用,你需要调用进程的引用和调用继续方法来执行实际的业务逻辑

package com.micai.spring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

/**
 * 描述:
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/6/11 17:31
 */
@Aspect
public class LoggingAspect {

    @Around("execution(* com.micai.spring.aop.BusinessLogic.getBusinessLogic(..))")
    public void loggingAroundBusinessLogic(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Before calling actual business logic"); // 在运行实际的业务逻辑之前
        joinPoint.proceed(); // 业务逻辑方法被执行
        System.out.println("After calling actual business logic"); // 在运行实际业务逻辑之后
    }


}

当您运行SpringAOPMain。java,您将得到以下输出:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Before calling actual business logic
*****************
In Business Logic method
*****************
After calling actual business logic

Process finished with exit code 0



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迷彩的博客

你的鼓励将是我最大的创作动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值