Spring提供了两种切面声明方式,实际工作中我们可以选用其中一种:
①基于XML配置方式声明切面,为AOP专门提供了aop命名空间
②基于注解方式声明切面,AspectJ切点表达式语言的支持。@AspectJ允许开发者在POJO中定义切面
采用注解方式实现(Annotation)步骤
①引入aspectJ类库
②在当前类上面加上注解-@component,加上去之后扫描这个类
package com.aspectJ.user;
public interface Iuser {
void printone();
void printtwo();
void printthree();
}
package com.aspectJ.user;
import org.springframework.stereotype.Component;
@Component
public class IuserImpl implements Iuser {
@Override
public void printone() {
System.out.println("hello world1");
}
@Override
public void printtwo() {
System.out.println("hello world2");
}
@Override
public void printthree() {
// TODO 自动生成的方法存根
System.out.println(10/0);
System.out.println("出现异常了");
}
}
③定义切面、切点和通知类型
package com.aspectJ.advice;
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;
//getSignature():返回被代理的目标方法
//getName():被代理的目标方法的名字
//@Component控制器(注入服务)
//@service 服务(注入dao)
//@component (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>)
@Component
@Aspect
public class Advice {
//声明一个公共切入点
@Pointcut("execution(* com.aspectJ.user.*.*(..))")
private void myPointCut() {
}
//替换前置
// @Before("execution(* com.aspectJ.user.*.*(..))")
@Before(value="myPointCut()")
public void before(JoinPoint joinPoint) {
//获得目标类方法的名称
System.out.println("前置通知:"+joinPoint.getSignature().getName());
}
//替换后置
@AfterReturning(value="myPointCut()",returning="obj")
public void after(JoinPoint joinPoint,Object obj) {
System.out.println("后置通知:"+joinPoint.getSignature().getName()+obj);
}
//替换环绕
//@Around(value="myPointCut()")
//public Object around(ProceedingJoinPoint jp)throws Throwable {
// System.out.println("前环绕:");
// Object obj = jp.proceed();
// System.out.println("后环绕:");
// return jp;
//}
//替换抛出异常
@AfterThrowing(value="myPointCut()",throwing="e")
public void afterThrowing(JoinPoint jp1,Throwable e){
System.out.println("抛出异常通知:"+e.getMessage());
}
//最终通知
@After(value="myPointCut()")
public void lastafter(JoinPoint jP2) {
System.out.println("最终通知:s"+jP2.getClass().getName());
}
}
④目标类所在的包,@component只有在扫描包之后才会起作用
<?xml version="1.0" encoding="UTF-8"?>
//applicationContext.xml
<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"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 1.扫描 注解类-->
<context:component-scan base-package="com.aspectJ.user,com.aspectJ.advice"></context:component-scan>
<!-- 2.确定aop注解生效 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>