赞
踩
本文主要讲解,AOP的几种不同实现方式,以及几种实现方式之间的关联,最后在补充AOP实现机制和原理
指具体的切口 , 譬如指定的具体包、层级、类、方法 execution(* cn.burcher.service.UserServiceImpl.*(..));
或者是 指定的注解@annotation(log)
切面的具体实现(增强),通知有五中不同的形式,决定了在不同的时间段做具体的实现,又或者说增强
通知和切点的结合,通知和切点共同定义了切面的全部内容,它是干什么的,什么时候在哪执行
把切面加入程序代码的过程。切面在指定的连接点被织入到目标对象中,在目标对象的生命周期里有多个点可以进行织入:
业务接口
package cn.burcher.service;
public interface UserService {
void add();
void delete();
void update();
void query();
}
业务实现类
package cn.burcher.service; public class UserServiceImpl implements UserService{ public void add() { System.out.println("添加了一个用户"); } public void delete() { System.out.println("删除了一个用户"); } public void update() { System.out.println("更新了一个用户"); } public void query() { System.out.println("查询了一个用户"); } }
前置通知:MethodBeforeAdvice
后置通知:AfterReturningAdvice
前置通知
package cn.burcher.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class LogBefore implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getSimpleName()+"的"+method.getName()+"方法执行了");
}
}
后置通知
package cn.burcher.log;
import org.springframework.aop.AfterAdvice;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class LogAfter implements AfterReturningAdvice {
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getSimpleName()+"的"+method.getName()+"方法执行了");
}
}
在beans.xml注册(注意:使用aop需要导入配置)
<bean id="logBefore" class="cn.burcher.log.LogBefore"/>
<bean id="logAfter" class="cn.burcher.log.LogAfter"/>
<bean id="userService" class="cn.burcher.service.UserServiceImpl"/>
<!--aop配置类-->
<aop:config>
<!--定义一个切入点-->
<aop:pointcut id="point" expression="execution(* cn.burcher.service.UserServiceImpl.*(..))"/>
<!--对切入点 执行 -->
<aop:advisor advice-ref="logAfter" pointcut-ref="point" />
<aop:advisor advice-ref="logBefore" pointcut-ref="point" />
</aop:config>
结果测试
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
}
结果:
UserServiceImpl的add方法执行了
添加了一个用户
UserServiceImpl的add方法执行了
编写自定义切面类
package cn.burcher.pointcut;
public class Log {
public void before(){
System.out.println("方法执行前");
}
public void after(){
System.out.println("方法执行后");
}
}
在beans.xml中配置
<bean id="log" class="cn.burcher.pointcut.Log"/>
<aop:config>
<aop:pointcut id="point" expression="execution(* cn.burcher.service.UserServiceImpl.*(..))"/>
<aop:aspect ref="log">
<aop:after method="after" pointcut-ref="point"/>
<aop:before method="before" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
测试类不变,再次执行
结果:
方法执行前
添加了一个用户
方法执行后
@Aspect 相当于aop:config
@Before相当于aop:before
package cn.burcher.pointcut; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class AnnotationPointcut { @Before("execution(* cn.burcher.service.UserServiceImpl.*(..))") public void before(){ System.out.println("========方法执行前========="); } @After("execution(* cn.burcher.service.UserServiceImpl.*(..))") public void after(){ System.out.println("========方法执行后========="); } @Around("execution(* cn.burcher.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("---------环绕前---------"); pjp.proceed(); System.out.println("---------环绕后---------"); } }
测试类不改,再次执行
---------环绕前---------
========方法执行前=========
添加了一个用户
========方法执行后=========
---------环绕后---------
通过上面的几个例子,都简单的知道了Aop的实现方式,但是上面三种也有缺陷,都是通过固定的层级来做切面,没有实现我们真正想要的,通过加注解动态实现aop,下面展示如何通过注解+aop实现动态配置
声明切面注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
String value() default "";
}
配置切面,声明注解为连接点,而不是具体的包层级
@Aspect @Component public class AnnotationAop { @Pointcut(value = "@annotation(log)", argNames = "log") public void pointcut(Log log) { } @Around(value = "pointcut(log)", argNames = "joinPoint,log") public Object around(ProceedingJoinPoint joinPoint, Log log) throws Throwable { try { System.out.println(log.value()); System.out.println("around"); return joinPoint.proceed(); } catch (Throwable throwable) { throw throwable; } finally { System.out.println("around"); } } } @Before("@annotation(com.jiuxian.annotation.Log)") public void before(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Log log = method.getAnnotation(Log.class); System.out.println("注解式拦截 " + log.value()); }
Service 方法实现测试
public interface UserService { String save(String user); void testAnnotationAop(); } @Service public class UserServiceImpl implements UserService { @Override public String save(String user) { System.out.println("保存用户信息"); if ("a".equals(user)) { throw new RuntimeException(); } return user; } @Log(value = "test") @Override public void testAnnotationAop() { System.out.println("testAnnotationAop"); } }
参考文章 :
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。