Spring使用注解的方式实现AOP的开发——Spring AOP(七)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34598667/article/details/83536346

上一章我们已经学过使用XML的方式实现AOP:
https://blog.csdn.net/qq_34598667/article/details/83502426
本章我们学习一下使用注解的方式实现AOP


Spring使用注解的方式实现AOP的开发


本章所需知识点

1、开启aop注解的自动代理

< aop:aspectj-autoproxy/>

2、 AspectJ的AOP的注解:

  • @Aspect:定义切面类的注解
  • 通知类型:
    @Before:前置通知
    @AfterReturing:后置通知
    @Around:环绕通知
    @After:最终通知
    @AfterThrowing:异常抛出通知.
  • @Pointcut:定义切入点的注解

3、切入点语法表达式(与xml方式一样)

语法:execution(表达式)
表达式语法:[方法访问修饰符] 方法返回值包名.类名.方法名(方法的参数)

例1:
execution (* com.oak.service.impl.UserServiceImpl.*(…)) :匹配UserServiceImpl类中声明的所有方法。
第一个 * :代表任意修饰符及任意返回值类型
第二个 * :代表任意方法,
… :匹配任意数量任意类型的参数,若目标类与该切面在同一个包中,可以省略包名。

例2:execution public double cn.itcast.service.impl.PersonServiceImpl.*(…):匹配PersonServiceImpl类中返回值类型为double类型的所有公有方法。


实现案例

本章案例基于上一章使用xml的方式实现AOP的项目上继续完成:

1)编写目标类

创建接口InfoService
public interface InfoService {
	void save(); 
	void update(); 
	void delete(); 
	void find(); 
}
创建实现类InfoServiceImpl
public class InfoServiceImpl implements InfoService{

	@Override
	public void save() {
		System.out.println("I am the method for save ");
	}

	@Override
	public void update() {
		System.out.println("I am the method for update ");
	}

	@Override
	public void delete() {
		System.out.println("I am the method for delete ");
	}

	@Override
	public void find() {
		System.out.println("I am the method for find ");
	}
}

2)配置目标类

<!--配置目标类 -->
<bean id="infoService" class="com.oak.service.InfoServiceImpl"></bean>

3)开启aop自动代理

<!--配置目标类 -->
<bean id="infoService" class="com.oak.service.InfoServiceImpl"></bean>
<!-- 开启aop的自动代理 -->
<aop:aspectj-autoproxy/> 

4)编写切面类MyAspectAnno

声明切入点和通知方法


@Aspect
public class MyAspectAnno {
	
	//声明一个切入点,anyMethod为切入点名称,指定切入点,哪些方法需要通知
	@Pointcut("execution (* com.oak.service.InfoService.*(..))")
	private void anyMethod(){}
	
	//声明该方法是一个前置通知:在目标方法开始之前执行 
	@Before("anyMethod()")
	public void doBeforeCheck() {
        System.out.println("前置通知");
    }
}

5)配置切面类

<!--配置切面类--> 
<bean id="myAspectAnno" class="com.oak.aop.MyAspectAnno"></bean> 

6)测试

在测试类中编写测试方法

@Test
public void aopAnnoTest(){
	ApplicationContext cxt = 
				 new ClassPathXmlApplicationContext
				 ("applicationContext.xml");
	InfoService infoService=cxt.getBean("infoService",InfoService.class);
	infoService.save();
}

测试结果是:

前置通知
I am the method for save 

7)其他通知

修改切面类,使用注解加上其他通知

@Aspect
public class MyAspectAnno {
	
	//声明一个切入点,anyMethod为切入点名称,指定切入点,哪些方法需要通知
	@Pointcut("execution (* com.oak.service.InfoService.*(..))")
	private void anyMethod(){}
	
	//声明该方法是一个前置通知:在目标方法开始之前执行 
	@Before("anyMethod()")
	public void doBeforeCheck() {
        System.out.println("前置通知");
    }
	@AfterReturning("anyMethod()")
    public void doAfterReturning() {
        System.out.println("后置通知");
    }

    @After("anyMethod()")
    public void doAfter() {
        System.out.println("最终通知");
    }

    @AfterThrowing("anyMethod()")
    public void doAfterThrowing() {
        System.out.println("异常通知");
    }

    @Around("anyMethod()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        /**
         * 环绕通知内部一定要确保执行该方法,如果不执行该方法,业务bean中被拦截的方法就不会被执行。
         * 当执行该方法,如果后面还有切面的话,它的执行顺序应该是这样的:先执行后面的切面,如果后面没有切面了,
         * 再执行最终的目标对象的业务方法。若不执行该方法,则后面的切面,业务bean的方法都不会被执行。
         */
        // if () { // 判断用户是否有权限,
        System.out.println("进入方法");
        Object result = pjp.proceed();
        System.out.println("退出方法");
        // }
        return result;
    }
}

注意:环绕通知内部一定要确保执行proceed()该方法,如果不执行该方法,业务bean中被拦截的方法就不会被执行。当执行该方法,如果后面还有切面的话,它的执行顺序应该是这样的:先执行后面的切面,如果后面没有切面了,再执行最终的目标对象的业务方法。若不执行该方法,则后面的切面,业务bean的方法都不会被执行。

运行测试:

进入方法
前置通知
I am the method for save 
退出方法
最终通知
后置通知

猜你喜欢

转载自blog.csdn.net/qq_34598667/article/details/83536346