SpringAOP的运用方式——注解方式和XML配置方式

SpringAOP的运用方式——注解方式和XML配置方式

AOP(Aspect Oriented Programming):面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

主要功能

日志记录,性能统计,安全控制,事务处理, 异常处理等等。

主要意图

将日志记录,性能统计,安全控制,事务处理, 异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
 
AOP在运用中,大体可以通过两种处理方式: 注解方式XML配置方式
(一)、注解方式
  a.controller
package controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping
public class ProjectController {
    @RequestMapping("/success/{param}")
    public String goContent(@PathVariable String param, Model model){
        System.out.println(param + "调用了 Controller");
        model.addAttribute("userName",param);
        return "/success";
    }
}
需要通过AOP自动添加日志的controller
  b.切面处理的逻辑
package north;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import java.io.IOException;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "controller")
@Aspect
public class AspectStyleNorth {
    @Pointcut("execution(* controller.*.*(..))")
    public void pointcut() {
        System.out.println("定义切点.....");
    }

    @Before(value="pointcut()")
    public void before() {
        System.out.println("AspectStyleNorth.before()方法执行前执行.....");
    }

    @After("pointcut()")
    public void after(JoinPoint joinPoint) throws IOException {
        System.out.println("AspectStyleNorth.after()方法执行后执行.....");
    }

    @Around(value="pointcut()")
    public Object around(ProceedingJoinPoint pjp){
        System.out.println("AspectStyleNorth.around()方法环绕start.....");
        Object rs = new Object();
        try {
            rs = pjp.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("AspectStyleNorth.around()方法环绕end.....");
        return rs;
    }

    @AfterThrowing(value="pointcut()", throwing="e")
    public void exception(Exception e) {
        //记录异常
        System.out.println("exception ["+e+"]");
    }

}
注解AOP处理的编写

  c.springmvc.xml中需要配置对 注解类的扫描

<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" 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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
>
    
    <context:component-scan base-package="north"></context:component-scan>

    <!-- 配置视图解析器 如何把handler 方法返回值解析为实际的物理视图 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>
springmvc.xml配置扫描

  d.效果

【说明】:around()与before() 开始执行的先后不确定,但before() 必定在around()中 proceedingJoinPoint.proceed()之前执行。

(二)、XML配置方式
  a.controller
package controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping
public class ProjectController {
    @RequestMapping("/success/{param}")
    public String goContent(@PathVariable String param, Model model){
        System.out.println(param + "调用了 Controller");
        model.addAttribute("userName",param);
        return "/success";
    }
}
需要通过AOP自动添加日志的controller
  b.springmvc.xml 的配置
<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" 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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
>
    
    <context:component-scan base-package="controller,server"></context:component-scan>
    
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* controller.*.*(..))"/>
        <aop:aspect ref="aspectStyleSouth">
            <aop:before pointcut-ref="pointcut" method="before"/>
            <aop:after pointcut-ref="pointcut" method="after"/>
            <aop:around pointcut-ref="pointcut" method="around"/>
            <aop:after-throwing pointcut-ref="pointcut" method="exception" throwing="e"/>
        </aop:aspect>
    </aop:config>

    <bean id="aspectStyleSouth" class="south.AspectStyleSouth"/>

    <!-- 配置视图解析器 如何把handler 方法返回值解析为实际的物理视图 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>
springmvc.xml对切面的配置

【注】:需要同时扫描两个地方的包:①AOP附加处理逻辑所在的包;②运用到 AOP 的业务逻辑所在的包。

  c.切面处理的逻辑
package south;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

import java.io.IOException;

@Aspect
public class AspectStyleSouth {

    public void before() {
        System.out.println("before方法执行前执行.....");
    }

    @Pointcut("execution(* server.*.*(..))")
    public void pointcutA() {
        System.out.println("定义切点.....");
    }

    @Before(value="pointcutA()")
    public void beforeA() {
        System.out.println("AspectStyleNorth.before()方法执行前执行.....");
    }


    /**
     *
     * @Title:doAfterInServiceLayer
     * @Description: 方法调用后触发
     *  记录结束时间
     * @author shaojian.yu
     * @date 2014年11月2日 下午4:46:21
     * @param joinPoint
     */
    public void after(JoinPoint joinPoint) throws IOException {
        Object[] args = joinPoint.getArgs() == null ? new String[]{""} : joinPoint.getArgs();
        System.out.println("after方法执行后执行....."+args[0]);
    }

    public Object around(ProceedingJoinPoint pjp){
        System.out.println("around方法环绕start.....");
        Object rs = new Object();
        try {
            rs = pjp.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("around方法环绕end.....");
        return rs;
    }

    public void exception(Exception e) {
        //记录异常
        System.out.println("exception ["+e+"]");
    }
}
XML配置方式中,对于的AOP需要添加的处理逻辑

  d.效果

项目的目录:

 

延伸:

1.在AOP中,需要用到传参的时,可参考:【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我学spring3

2.AOP中,方法、路径、参数等匹配的表达式,可参考:Aspectj execution表达式

 

猜你喜欢

转载自www.cnblogs.com/bridgestone29-08/p/11349536.html