SpringAOP简单例子

转自:https://blog.csdn.net/lp1052843207/article/details/52460601
AOP(Aspect-OrientedProgramming,面向切面编程,好多人喜欢说面向方面编程,我觉得切面更容易解释AOP。)

面向切面编程,有效的降低了代码之间的耦合性,易于维护;例如:我们习惯在代码中加上一些日志信息,在程序出错时方便快速查找找到问题,通常做法是在请求进入方法的时候打印日志,退出前打印日志,还有在出错时打印日志,那么问题就来了,每个方法中都需要打印日志,这些相同的部分就可以当做一个切面,通过配置切点来触发所需要的功能,比如,我需要在请求进入方法的时候打印,即可使用aop当中的前置通知来做到,这样就不需要每个方法中都去写一遍,配置好之后引用即可。

aop代码实例:

1.创建一个控制台程序;导入包

2.创建接口

package com.AspectTest.service;
public interface personServer {
    public void save(String uname,int age); 
}

3.接口的实现

package com.AspectTest.service;
public class personServerImpl implements personServer{
    @Override
    public void save(String uname,int age) {
        int a=0;
        age= age/a;//打开上面两行报错,可触发异常通知
        System.out.println("come in personServerImpl save method...");
    }
}

4.创建(aop)切面类

package com.AspectTest.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
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;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect//声明这是一个切面
@Component//声明这是一个组件,泛指...可以去掉
public class AspectIntercepter {

      @Pointcut(value="execution(* com.AspectTest.service.personServerImpl.*(..))")
      private void pointCut(){//定义一个切入点 后面的通知直接引入切入点方法pointCut即可            personServerImpl下面的所有方法
      }

       //环绕通知(连接到切入点开始执行,下一步进入前置通知,在下一步才是执行操作方法)
        @Around(value="pointCut()")
        public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{
            System.out.println("@Around进入环绕通知...");
            Object object = pjp.proceed();//执行该方法
            System.out.println(pjp.getThis()+"  操作结束,退出方法;环绕[@Around]结束!...");
            return object;
        }

        //前置通知(进入环绕后执行,下一步执行方法)
        @Before(value="pointCut()")
        public void doAccessCheck(JoinPoint joinPoint){
            System.out.println("@Before前置通知:"+Arrays.toString(joinPoint.getArgs()));
        }

        //异常通知(出错时执行)
        @AfterThrowing(value="pointCut()",throwing="ex")
        public void doAfterThrow(JoinPoint joinPoint,Throwable ex){
            System.out.println("@AfterThrowing例外通知(异常通知)"+Arrays.toString(joinPoint.getArgs()));
            System.out.println("@AfterThrowing异常信息:"+ex);
        }

        //后置通知(返回之前执行)
        @After(value="pointCut()")
        public void after(){
            System.out.println("@After后置通知...");
        }

        //最终通知(正常返回通知,最后执行)
        @AfterReturning(value="pointCut()")
        public void doAfter(){
            System.out.println("@AfterReturning最终通知...End!");
        }
}

5.配置aop配置文件

<?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"
    xmlns:context="http://www.springframework.org/schema/context"
    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.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!-- 使 AspectJ 的注解起作用 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <bean id="personServiceBean" class="com.AspectTest.service.personServerImpl"/>  
    <bean id="myInterceptor" class="com.AspectTest.aop.AspectIntercepter"/> 

</beans>

6.创建测试类

package com.AspectTest;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.AspectTest.service.personServer;
public class SpringAopTest {
        @Test
        public void inteceptorTest(){
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-aop.xml");
            personServer bean = (personServer)ctx.getBean("personServiceBean");
            bean.save("badMonkey",23);

//          personServer p = new personServerImpl();//通过new对象是不会触发aop的
//          p.save("11", "22");
        }
}

【运行结果1】:
@Around进入环绕通知…
@Before前置通知:[badMonkey, 23]
come in personServerImpl save method…
com.AspectTest.service.personServerImpl@11023cad 操作结束,退出方法;环绕[@Around]结束!…
@After后置通知…
@AfterReturning最终通知…End!

【运行结果2】:

@Around进入环绕通知…
@Before前置通知:[badMonkey, 23]
@After后置通知…
@AfterThrowing例外通知(异常通知)[badMonkey, 23]
@AfterThrowing异常信息:java.lang.ArithmeticException: / by zero

注:

AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法:
1)JoinPoint
 java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
 Signature getSignature() :获取连接点的方法签名对象;
 java.lang.Object getTarget() :获取连接点所在的目标对象;
 java.lang.Object getThis() :获取代理对象本身;
2)ProceedingJoinPoint
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:
 java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
 java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Spring AOP(面向切面编程)是Spring框架中的一个关键特性,它允许开发者在不修改原始代码的情况下,通过切入点和通知来实现横切关注点的功能。 下面我给出一个简单的Spring AOP的例子来解释其工作原理。 假设我们有一个Spring应用程序,其中包含一个名为UserService的服务类,负责处理用户相关的业务逻辑,比如验证用户、保存用户等操作。 首先,我们需要定义一个切入点(Join point),用来确定在UserService的哪些方法上我们需要应用AOP。例如,我们可以将切入点定义为所有保存用户的方法。 其次,我们需要定义通知(Advice),它是在切入点之前或之后执行的代码逻辑。例如,我们可以定义一个前置通知(Before advice)来在保存用户之前验证用户的信息。 接下来,我们需要将切入点和通知组合起来,创建一个切面(Aspect)。切面是一个类,它包含了切入点和通知,并指定了在切入点上何时应用通知。在我们的例子中,切面可以是一个名为ValidationAspect的类,其中定义了一个前置通知方法。 最后,我们需要将切面配置为Spring容器的一部分。我们可以通过在Spring的配置文件中声明一个<aop:aspectj-autoproxy>元素来完成这一配置。这样,当应用程序启动时,Spring容器会自动为我们创建切面。 当我们调用UserService的保存用户方法时,Spring AOP就会根据切面配置来决定是否将前置通知应用于该方法。如果切入点的条件匹配,前置通知会提前执行验证用户的逻辑。 通过这个例子,我们可以看到,Spring AOP提供了一种非侵入式的方式来增强代码的功能,使得我们可以在不修改原始代码的情况下,通过切入点和通知来实现横切关注点的功能。这样可以提高代码的模块化和可重用性,降低代码的复杂性。 ### 回答2: Spring AOP(面向切面编程)是Spring框架中的一个重要特性,用于在不改变原有代码的情况下增加功能和耦合性。它通过将主要的业务逻辑(核心业务)与横切关注点(如日志记录、事务管理等)分离来实现。 下面是一个可以帮助理解Spring AOP的例子:假设我们有一个简单的应用程序,其中包含一个Service层的类来处理用户的注册请求。在用户注册成功后,我们希望自动生成一个欢迎邮件,同时在控制台中记录下来。这里就可以使用Spring AOP来实现。 首先,我们需要定义一个切面类来处理横切关注点,例如记录日志和发送欢迎邮件。切面类应该实现通知(Advice)。在这个例子中,我们可以使用@Before通知来在目标方法执行之前发送欢迎邮件,并使用@After通知在目标方法执行之后记录日志。 接下来,在Spring配置文件中进行配置。我们需要定义一个切点(Pointcut),以告诉Spring在哪些方法上应用切面。在这个例子中,我们可以使用execution()表达式定义一个切点,以匹配Service层中的所有方法。 最后,在Service层的类中,我们需要使用一个@Autowired注解将切面类注入到目标类中。这样,当Service层中的方法被调用时,切面类就会自动执行。 通过这个例子,我们可以清楚地看到Spring AOP如何帮助我们将横切关注点与核心业务分离,并在不改变原有代码的情况下实现功能的增强。这样,我们可以更容易地维护、扩展和重用代码,提高系统的可维护性和灵活性。 ### 回答3: Spring AOP是Spring框架中的一个关键特性,它提供了一种方法来通过动态代理技术在应用程序的不同层之间添加横切关注点。 举一个简单例子来说明Spring AOP的用法。假设我们有一个电商网站,我们想要在用户购买商品之前验证用户的身份。我们可以通过使用Spring AOP来实现这个功能。 首先,我们需要定义一个切面(Aspect),用于对购买商品的方法进行拦截和处理。我们可以创建一个类,并在其中定义一个方法,使用@Before注解来标记它。在这个方法中,我们可以编写代码来验证用户的身份,例如检查用户是否已登录。 然后,我们需要配置Spring AOP,告诉它在哪些类和方法上应用这个切面。我们可以在Spring配置文件中使用<aop:aspectj-autoproxy>元素来启用自动代理,然后在<aop:config>元素中定义切面的位置和应用规则。 接下来,我们需要在我们的购买商品方法上添加一个标记(Annotation),以告诉Spring AOP对该方法应用切面。我们可以在方法上添加一个自定义的注解,例如@RequiresAuthentication。然后,我们可以在切面的方法中使用@Pointcut注解来指定切入点,即哪些方法应该被拦截。 最后,我们可以测试这个例子。我们可以创建一个控制器(Controller),其中有一个方法用于购买商品。当用户调用该方法时,Spring AOP会自动拦截并执行切面中的逻辑,验证用户的身份是否合法。如果用户未登录或身份验证失败,可以抛出异常或返回错误信息。 综上所述,Spring AOP是一个非常强大的功能,可以帮助我们在应用程序中实现横切关注点,提高代码的模块化和可维护性。以上是一个简单例子,展示了如何使用Spring AOP来验证用户身份。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值