SpringAop介绍与实战
AOP: Aspect Oriented Programming ,面向且边切面编程,即在不破坏原有对象、不需要更改原代码的基础上,实现方法功能的增强。说切面,是因为它不需要像传统OOP那样,纵向继承,只需要横向扩展即可。
AOP的实现可通过AspectJ以及Spring AOP两种方案,Spring并不是直接使用AspectJ,但其使用了AspectJ的注解方案,随后在运行时通过动态代理生成代理类。AspectJ是在编译时注入的。
在AOP中比较重要的几个概念:
1、Target:目标类,需要被增强的类。
2、JointPoint:连接点,目标类上每一个方法都可以是连接点。这个很好理解,AOP是基于动态代理的。
3、PointCut:切入点,被增强的方法,切入点就是一个连接点的子集
4、Advice:增强/通知,增强的代码,也就是上面将增强的代码凑成的一个类。类中的每个方法都代表一个增强的功能代码,这个类中的方法就被称为通知。pring AOP提供了5种Advice类型:前置、后置、返回、异常、环绕。
5、weaving:织入,将切入点和通知结合,从没被增强到已经增强的过程
6、Aspect:切面,切入点和通知结合,切入点 和 通知点 多点形成面。
例子1:
1、实现AOP Bean,
@Slf4j
@Component
@Aspect
public class ProxyAop {
@Pointcut("execution(public * com.hnshop.hbnnshop.prac..*.*(..))")
private void controllerAspect(){}
@Around("controllerAspect()")
public Object handleControllerMethod(ProceedingJoinPoint pjp) {
log.info("start to execute aop method ");
try
{
return pjp.proceed(pjp.getArgs());
}catch (Throwable e){
log.error(e.getMessage());
return "server error";
}
}
@Before("controllerAspect()")
public void before(){
log.info("before aop method exec");
}
@After("controllerAspect()")
public void after(){
log.info("after aop method");
}
}
上面几个注解的意思:
2.1 @Aspect
作用是把当前类标识为一个切面供容器读取。此时所有涉及到的Bean都会创建代理对象。但该类本身不会。
2.2 @Before
标识一个前置增强方法,相当于BeforeAdvice。
2.3 @AfterReturning
后置增强,相当于AfterReturningAdvice,方法正常退出时执行
2.4 @AfterThrowing
异常抛出增强,相当于ThrowsAdvice
2.5 @After
final增强,不管是抛出异常或者正常退出都会执行
2.6 @Around
环绕增强,相当于MethodInterceptor
我们要测试一个目标类:
@Component
public class IeratorPra {
public List<Integer> getList(){
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
return list;
}
public void testIteratorRemove(){
List<Integer> list = this.getList();
ListIterator<Integer> integerListIterator = list.listIterator();
while (integerListIterator.hasNext()){
if(integerListIterator.next() == 4){
integerListIterator.remove();
}
}
System.out.println(list);
}
}
调用:
public class ListPra extends HbnnshopApplicationTests {
@Autowired
IeratorPra ieratorPra;
@Test
public void test(){
System.out.println(ieratorPra.getClass().getName());
ieratorPra.testIteratorRemove();
}
测试一下输出结果:
看到输出结果可以看到,生成了一个代理对象,且因为目标类没有实现接口,所以使用了CGLIB代理。
例子二(通过注解的方式)
定义注解和AOP:
//目标方法
@Target(ElementType.METHOD)
//保留到JVM
@Retention(RetentionPolicy.RUNTIME)
//JAVADOC
@Documented
//自动继承
@Inherited
public @interface TestAno {
}
@Slf4j
@Component
@Aspect
public class TestAop {
@Pointcut("@annotation(com.hnshop.hbnnshop.core.annotation.TestAno)")
private void annoAspect(){}
@Around("annoAspect()")
public Object handleControllerMethod(ProceedingJoinPoint pjp) {
log.info("start to execute aop method ");
try
{
return pjp.proceed(pjp.getArgs());
}catch (Throwable e){
log.error(e.getMessage());
return "server error";
}
}
@Before("annoAspect()")
public void before(){
log.info("before aop method exec");
}
@After("annoAspect()")
public void after(){
log.info("after aop method");
}
}
目标类的方法使用注解:
@TestAno
public void testIteratorRemove(){
List<Integer> list = this.getList();
ListIterator<Integer> integerListIterator = list.listIterator();
while (integerListIterator.hasNext()){
if(integerListIterator.next() == 4){
integerListIterator.remove();
}
}
System.out.println(list);
}
输出结果和上面类似:
参考资料:
微信分享/微信扫码阅读