实现Aop的方式有两种:
1.xml配置文件方式
首先写出目标类,目标类中有目标方法即切入点,例如
@Repository
public class Dao implements IDao{
@Override
// 切入点
public void add() {
// TODO Auto-generated method stub
System.out.println("add info");
}
@Override
public void delete() {
// TODO Auto-generated method stub
System.out.println("delete info");
}
}
其次,需要有自己的切面类,切面类中包含关注点:例如
// 切面类
@Component
public class LogAop {
// 关注点
// 参数 JoinPoint ,切入点对象,根据实际需求,可写可不写
public void begin(JoinPoint jp){
System.out.println("befor");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
// 方法名
String name = jp.getSignature().getName();
// 类名
String cName = jp.getSignature().getDeclaringTypeName();
//jp.getArgs();//获取方法的参数
System.out.println("开始执行方法:" + cName + "." + name + ",执行时间:" + sdf.format(new Date()));
// System.out.println("执行时间:" + sdf.format(new Date()));
}
public void end(){
System.out.println("after");
}
// 正常返回通知要执行的方法
public void afterReturn(){
System.out.println("after return");
}
// 环绕通知要执行的方法,必须要使用ProceedingJoinPoint 参数,表示切入点信息的对象
public void around(ProceedingJoinPoint pjp){
// 获取执行的方法的方法名
System.out.println("around befor:" + pjp.getSignature().getName());
try {
// 执行目标方法
pjp.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("around after");
}
}
再者,需要在bean.xml配置文件中配置引入切面类,配置如下:
<!--扫描相关注解,即扫描例如@Component这些注解 -->
<context:component-scan base-package="xmlaop"></context:component-scan>
<!--针对aop的配置 -->
<aop:config>
<!--配置切入点 ,配置切入点表达式
execution(访问权限 包名.类名.方法名(参数));
第一个*表示所有的访问的权限
第二个*(..)表示的任意方法名,任意参数
本例子中,Dao类中所有的方法都是切入点
-->
<aop:pointcut expression="execution(* xmlaop.Dao.*(..))" id="pc"/>
<!--配置切面类 ref:引入一个对象
method:前置通知要执行的方法
point-cut:切入点的引用
-->
<aop:aspect ref="logAop">
<!--前置通知 -->
<aop:before method="begin" pointcut-ref="pc"/>
<!--后置通知 -->
<aop:after method="end" pointcut-ref="pc"/>
<!--正常返回通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="pc"/>
<!--环绕通知 -->
<aop:around method="around" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
2.注解方式
还可以直接在切面类上使用注解的方式配置切入点
首先,还是先写目标对象,即目标对象中有目标方法即切入点
@Component
public class Dao implements IDao{
@Override
// 切入点
public void add() {
// TODO Auto-generated method stub
System.out.println("add info");
}
@Override
public void delete() {
// TODO Auto-generated method stub
System.out.println("delete info");
}
}
其次,写出切面类,直接使用注解的方式在关注点上面配置切入点
//动态扩展功能
//切面类
@Component
//表示修饰的类是一个切面类
@Aspect
public class LogAop {
// 如果所有的通知使用相同的切入点,就需要额外定义一个方法
@Pointcut("execution(* annoaop.Dao.*(..))")//配置切入点
public void pointcut() {
}
//关注点(通知,增强)
// 参数可以不写,JoinPoint获取切入点接口对象,即可以获取执行的方法名
// @Before("execution(....)")
@Before("pointcut()")//通过配置切入点的方法名来引用相关的切入点
public void begin(JoinPoint joinPoint) {
System.out.println("before");
// 方法执行之前
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getSignature().getDeclaringTypeName();
String string = format.format(new Date());
System.out.println(string + "开始执行;" + methodName + ";" + className);
}
@After("pointcut()")//后置通知
public void end() {
System.out.println("after");
}
// 正常返回通知执行的方法
@AfterReturning("pointcut()")
public void afterReturn() {
System.out.println("after return");
}
// 环绕通知必须给参数,且必须使用ProceedingJoinPoint的参数,表示的是切入点信息
@Around("pointcut()")
public void around(ProceedingJoinPoint point) {
// 获取执行方法的方法名
System.out.println("around before" + point.getSignature().getName());
try {
// 执行目标方法
point.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("around after");
}
}
再者,在配置文件中扫描相关的注解
<!--扫描相关注解 只会扫描依赖注入以及控制反转的代码-->
<context:component-scan base-package="annoaop"></context:component-scan>
<!--扫描aop的注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
网友评论