JavaEE:Spring AOP用法

说明:

AOP:面向切面编程,通过预编译方式和运行期动态代理实现功能的一种技术,对业务各个部分隔离,降低耦合。

AspecjJ:AOP实现框架。

通用依赖jar包:commons-logging-x.x.jar、log4j-x.x.xx.jar

spring依赖jar包:spring-core-x.x.x.RELEASE.jar、spring-context-x.x.x.RELEASE.jar、spring-beans-x.x.x.RELEASE.jar、spring-expression-x.x.x.RELEASE.jar、spring-aop-x.x.x.RELEASE.jar、spring-aspects-x.x.x.RELEASE.jar

AspecjJ依赖jar包:aspectjweaver-x.x.x.jar、aopalliance-x.x.jar

术语:

Joinpoint:连接点,可以被拦截的点(方法)。
Pointcut:切入点,真正被拦截的点(方法)。
Advice:通知、增强,方法层面的,对方法进行权限校验,权限校验的方法就是通知。
通知分类:
前置通知:在目标方法前执行。
后置通知(返回通知):在目标方法后执行。
环绕通知:在目标方法前与后都执行。
异常抛出通知:出现异常时执行。
最终通知:不管是否出现异常,总是执行。
引介通知:目标类能同时继承多个实现类
Introduction:引介,类层面的增强
Target:被增加的对象
Weaving:织入,将通知应用到目标对象方法的过程
Proxy:代理对象
Aspect:切面,多个通知+多个切入点组合的统称

一、xml方式,配置切面类、通知方法:

1.创建自定义切面类:

//自定义切面类
public class XmlAspecjJ {
    // 在目标方法前执行
    public void onInsertBefore() {}
    // 在目标方法后执行
    public void onInsertAfter() {}
    //在目标方法前与后都执行
    public void onInsertBeforeAndAfter() {}
    //出现异常时执行, 参数名t要和<aop:after-throwing>节点throwing值一致
    public void onInsertException(Throwable t) {}
    //不管是否出现异常,总是执行
    public void onFinally() {}
}

2.配置切面类,在applicationContext.xml的<beans>节点内配置:

(1)<aop:pointcut>节点的expression属性值说明:

格式:
execution(返回值 包名.类名.方法名(参数列表))

例:
execution(* com.yyh.hkw.dao.*Dao.*(..))

解释:
*表示任意字符或类型
除了参数必须用“..”或具体类型,其他都可以用*表示
第1个*指返回值类型可以任意值
第2个*指以Dao结尾的类
第3个*指任意方法
..指任意参数

(2)配置切面类,使用<aop:config>节点:

<?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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 让spring创建对象 -->
    <bean id="userDao" class="com.yyh.hkw.dao.UserDao"/>

    <!-- 一、让spring创建XmlAspecjJ自定义对象 -->
    <bean id="xmlAspecjJ" class="com.yyh.hkw.dao.XmlAspecjJ" />
    <!-- 二、配置XmlAspecjJ为切面类 -->
    <aop:config>
        <!-- 1.配置表达式,哪个类哪个方法需要增强,这里增强UserDao类的insert方法;第1* 表示任意返回值,..表示方法有任意个参数;id为引用名,供后面使用 -->
        <aop:pointcut expression="execution(* com.yyh.hkw.dao.UserDao.insert(..))" id="pointcutId" />
        <!-- 2.配置切面类,xmlAspecjJ为<bean>节点id的值 -->
        <aop:aspect ref="xmlAspecjJ">
            <!-- (1)配置前置通知,在目标方法前执行,onInsertBefore为 XmlAspecjJ类中自定义方法。pointcutId为<aop:pointcut>节点id的值-->
            <aop:before method="onInsertBefore" pointcut-ref="pointcutId" />
            <!-- (2)配置后置通知(返回通知),在目标方法后执行,onInsertAfter为 XmlAspecjJ类中自定义方法。pointcutId为<aop:pointcut>节点id的值-->
            <aop:after-returning method="onInsertAfter" pointcut-ref="pointcutId" />
            <!-- (3)配置环绕通知(前置+后置),在目标方法前与后都执行,onInsertBeforeAndAfter为 XmlAspecjJ类中自定义方法。pointcutId为<aop:pointcut>节点id的值-->
            <aop:around method="onInsertBeforeAndAfter" pointcut-ref="pointcutId" />
            <!-- (4)异常抛出通知,出现异常时执行,onInsertException为 XmlAspecjJ类中自定义方法。pointcutId为<aop:pointcut>节点id的值。throwing将异常传给自定义方法,t为方法参数名-->
            <aop:after-throwing method="onInsertException" pointcut-ref="pointcutId" throwing="t" />
            <!-- (5)最终通知,不管是否出现异常,总是执行,onFinally为 XmlAspecjJ类中自定义方法。pointcutId为<aop:pointcut>节点id的值-->
            <aop:after method="onFinally" pointcut-ref="pointcutId" />
            <!-- (6)声明使用引入通知,目标类能同时继承多个实现类 -->
            <!-- <aop:declare-parents types-matching="* 目标类父接口全名" implement-interface="被继承类的父接口全名" default-impl="被继承类的全名" /> -->
        </aop:aspect>
    </aop:config>

</beans>

二、注解方式,配置切面类、通知方法:

1.添加aop注解支持,在applicationContext.xml中beans节点中加入:

<!-- 添加aop注解支持 -->
<aop:aspectj-autoproxy/>

2.创建切面类:

(1)在类前添加注解,使用@Aspect标为切面类:

@Aspect //@Aspect标识此类为切面类
public class XmlAspecjJ {
}

(2)配置切面类,在applicationContext.xml中beans节点中加入:

<!-- 让spring创建XmlAspecjJ自定义对象 -->
<bean id="xmlAspecjJ" class="com.yyh.hkw.dao.XmlAspecjJ" />

3.在切面类中方法前加上注解:

(1)@Before,前置通知:

// 在目标方法前执行
@Before(value = "execution(* com.yyh.hkw.dao.UserDao.insert(..))")
public void onBefore() {
    System.out.println("onBefore");
}

(2)@AfterReturning返回通知(后置通知):

// 在目标方法后执行
@AfterReturning(value = "execution(* com.yyh.hkw.dao.UserDao.insert(..))")
public void onAfter() {
}

(3)@Around,环绕通知:

//在目标方法前与后都执行
@Around(value = "execution(* com.yyh.hkw.dao.UserDao.insert(..))")
public void onBeforeAndAfter(ProceedingJoinPoint joinPoint) throws Throwable {
    //1.方法之前
    joinPoint.getSignature().getName();// 取得在执行的方法名
    joinPoint.getArgs();// 取得在执行方法的参数列表
    //2执行方法
    joinPoint.proceed();
    //3.方法之后
}

(4)@AfterThrowing,异常通知:

//出现异常时执行, 参数名t要和throwing值一致
@AfterThrowing(value = "execution(* com.yyh.hkw.dao.UserDao.insert(..))", throwing = "t")
public void onException(Throwable t) {
    System.out.println("onException: " + t.getMessage());
}

(5)@After,最终通知:

//不管是否出现异常,总是执行
@After(value = "execution(* com.yyh.hkw.dao.UserDao.insert(..))")
public void onFinally() {

}

(6)@DeclareParents,引介通知(目标类能同时继承多个实现类):

在切面类方法前加上注解,让目标接口实现类继承了别的接口实现类中的方法
@DeclareParents(value="目标接口全名", defaultImpl=被继承类的全名)
在程序中调中
被继承类的父接口 别名 = (被继承类的父接口)目标接口;

4.@Order,指定切面类的优先级:

@Aspect()
@Order(1) //放在@Aspect后面,数字小的切面类先执行
public class XmlAspecjJ {
}

5.@Pointcut,定义通用切入点方法,供其他方法调用:

(1)在公用方法前加入注解:

@Pointcut("execution(* com.yyh.hkw.dao.UserDao.insert(..))")
public void onCommon() {
}

(2)在其他方法前的注解处引用公用方法:

// 引用onCommon()方法,共用onCommon方法中定义的切入表达式
@Before("onCommon()")  //在别的类中引用此公用定义:@Before("XmlAspecjJ.onCommon()")
public void onBefore() {
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值