Spring AOP技术的使用

本文介绍了Spring AOP的概念,强调了其在代码复用中的作用。通过添加AspectJ相关依赖,配置Spring的aop:aspectj-autoproxy,创建@Aspect切面类并定义通知方法,实现面向切面的编程。测试代码验证了AOP的执行过程。

AOP(Aspect Oriented Programming 面向切面编程)是一种指在程序运行期间动态的将某段代码切入到指定方法的指定位置进行运行的编程方式,这种编程方式实现了代码复用,是对传统OOP(Object Oriented Programming,面向对象编程 )的补充。目前,Aspectj是Java社区里最完整最流行的AOP框架,在Spring 2.0以上版本中可以通过Aspectj注解或基于XML配置AOP。

1、在pom.xml中进行maven配置,添加jar包

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>2.6.1</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.39</version>
</dependency>

2、Spring配置文件application.xml中添加<aop:aspectj-autoproxy/>

<!--找到切片类即由@Aspect注解的类,对其中切入点表达式中匹配的类生成代理类-->
<!--proxy-target-class默认是false,则由JDK自动生成代理类;若为true,则由CGLIB生成代理类-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

3、自定义一个@Aspect修饰的切面类——>将其创建的对象保存于Spring IOC容器——>自定义增强方法,增强方法也称为通知方法,指有@Before、@AfterRunning、@AfterThrowing、@After或@Around注解修饰的Java方法。

package com.jd.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class CalculatorAspect {

    @Pointcut("execution(public int com.jd.calculator.service.CalculatorService.*(..))")
    //切入点表达式:用于指定执行哪些类中的哪些方法时触发增强方法,
    public void pointcut(){
    }

    @Before("pointcut()")
    public void before(JoinPoint jp){
        Object [] args = jp.getArgs();
        String name = jp.getSignature().getName();
        System.out.println("The "+name+" method begins");
        System.out.println("The parameters of the "+name+" method are "+args[0]+","+args[1]);
    }

    @After("pointcut()")
    public void after(JoinPoint jp){
        String name = jp.getSignature().getName();
        System.out.println("The "+name+" method ends");
    }

    @AfterReturning(value="pointcut()",returning = "obj")
    public void afterReturning(JoinPoint jp,Object obj){
        String name = jp.getSignature().getName();
        System.out.println("The "+name+" method result:"+obj);
    }

    @AfterThrowing(value="pointcut()",throwing = "e")
    public void afterThrowing(JoinPoint jp,Throwable e){ //Throwable是所有异常类的父类
        System.out.println("##########"+e.getMessage());
    }

    /*@Around("pointcut()") //可替代以上四种注解
    public Object around(ProceedingJoinPoint jp){
        try {
            String name = jp.getSignature().getName();
            Object result = null;
            try {
                Object [] args = jp.getArgs();
                System.out.println("The "+name+" method begins");
                System.out.println("The parameters of the "+name+" method are "+args[0]+","+args[1]);//@Before注解所修饰的方法
                result = jp.proceed();//执行目标对象内的方法
            } finally {
                System.out.println("The "+name+" method ends");//@After注解所修饰的方法
            }
            System.out.println("The "+name+" method result:"+result);//@AfterReturning注解所修饰的方法
            return result;
        } catch (Throwable e) {
            System.out.println("##########"+e.getMessage());//@AfterThrowing注解所修饰的方法
        }
        return -1;
    }*/
}

4、去掉CalculatorService类中方法内输出语句,如下代码:

package com.jd.calculator.service;

import org.springframework.stereotype.Service;

@Service
public class CalculatorService implements ICalculatorService{
    @Override
    public int add(int a, int b) {
        int retult = a+b;
        return retult;
    }

    @Override
    public int div(int a, int b) {
        int retult = a/b;
        return retult;
    }

    @Override
    public int mul(int a, int b) {
        int retult = a*b;
        return retult;
    }
}

5、编写测试代码,代码如下:

import com.jd.calculator.service.ICalculatorService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);

        //<aop:aspectj-autoproxy></aop:aspectj-autoproxy>  proxy-target-class默认为false JDK:代理类是目标类接口的实现类
        System.out.println(calculatorService.getClass().getName());//com.sun.proxy.$Proxy8
        System.out.println(calculatorService.getClass().getInterfaces()[0].getName());//com.jd.calculator.service.ICalculatorService
        //变量calculatorService指向代理类$Proxy8创建的对象,而代理类$Proxy8又实现了ICalculatorService类
        calculatorService.add(1,2);//调用由$Proxy8类创建的对象中的add方法
        applicationContext.close();
     }       
}

执行过程:

try {
	try {
		doBefore();// @Before注解所修饰的方法
		method.invoke();// 执行目标对象内的方法
	} finally {
		doAfter();// @After注解所修饰的方法
	}
	doAfterReturning();// @AfterReturning注解所修饰的方法
} catch (Exception e) {
	doAfterThrowing();// @AfterThrowing注解所修饰的方法
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值