17Spring_AOP编程(AspectJ)_AspectJ的注解编程

时间:2023-03-08 19:25:15

前面的各种Aop编程,都是基于XML的,这篇文章讲的是把XML方式改为注解方式来做。

Spring注解开发和xml开发所需要的包是一样的,所以只要把xml开发方式的包复制到以注解为开发方式的包的项目下就可以了。

第一步:导入相应的jar包

第二步:需要在applicationContext.xml中引入aop的名称空间

开启注解自动代理:

<!-- 自动注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

第三步:AOP编程:

第(一)步.目标对象:

//编写目标类(真正被代理的)
public class UserDaoImpl implements UserDao { public int delete() {
System.out.println("删除了");
return 1; } }

第(二)步:编写切面类和Advice方法

//这个注解表明这个类就是切面类,在这个类里面可以写Advice(通知)方法。
@Aspect
public class Myspect {
//我们配置一个前置方法的Advice方法,这是一个Advice方法,当然要配置切点了。配了切点就表示在这个切点执行这个Advice方法。
@Before("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))")
public void before1(JoinPoint joinPoint)
{
System.out.print("this is 前置方法");
}
//后置通知,这是一个Advice方法,当然要配置切点了。配了切点就表示在这个切点执行这个Advice方法。
@AfterReturning(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",returning="returnVal")
public void afterReturning(JoinPoint joinPoint,Object returnVal)
{
System.out.println("this is afterReturning 方法");
System.out.println(returnVal); } }

第四步:在Spring配置文件中配置目标Bean和切面Bean

<!-- xml配置目标bean和切面bean -->
<bean id="UserDao" class="com.guigu.shen.anotion.UserDaoImpl"></bean>
<bean id="Myspect" class="com.guigu.shen.anotion.Myspect"></bean>

接下来给出Aspect5种通知的注解形式的具体实例

前置通知@Before

//前置通知
@Before("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))")
public void before1(JoinPoint joinPoint)
{
System.out.print("this is 前置方法");
}

后置通知:

//后置通知
@AfterReturning(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",returning="returnVal")
public void afterReturning(JoinPoint joinPoint,Object returnVal)
{
System.out.println("this is afterReturning 方法");
System.out.println(returnVal); }

环绕通知:

//环绕通知,在方法的前后执行,在工作中可以计算方法执行的时间,性能的监控,权限的设置,缓存的实行等
@Around("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
{
long begintime=System.currentTimeMillis();
Object result=proceedingJoinPoint.proceed();
long endtime=System.currentTimeMillis();
System.out.println("方法执行了"+(endtime-begintime)+"时间");
return result; }

异常通知:指的是当发生一些异常时会输出异常信息(如果方法没有异常的话,这个通知不会被执行的,比如如果.UserDaoImpl中的delete()方法会产生一个异常,

那么这个切点通知方法会执行,如果UserDaoImpl中的delete()方法没哟异常就不会执行这个方法)

@AfterThrowing(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",throwing="e")
public void afterThrowing(JoinPoint joinPoint,Exception e)
{
System.out.print(joinPoint.toLongString()+"方法发生了异常"+e.getMessage());
}

情形一:

被代理类的方法:

//编写目标类(真正被代理的)
public class UserDaoImpl implements UserDao { public int delete() {
System.out.println("删除了");
//int a=1/0;
return 1; } }

测试方法:

@Test
public void deletetest()
{
userDao.delete();
}

结果:不会输出异常的信息。

情形二:

被代理类的方法:

//编写目标类(真正被代理的)
public class UserDaoImpl implements UserDao { public int delete() {
System.out.println("删除了");
int a=1/0;
return 1; } }

测试方法:

@Test
public void deletetest()
{
userDao.delete();
}

结果:execution(public abstract int com.guigu.shen.anotion.UserDao.delete())方法发生了异常/ by zero18:36:25,064  INFO GenericApplicationContext:1042 - Closing org.springframework.context.support.GenericApplicationContext@24f9fdc: startup date [Mon Aug 01 18:36:07 CST 2016]; root of context hierarchy

最终通知:

@After("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))")
public void after()
{
System.out.print("最终通知,释放资源"); }

结果:

this is 前置方法

删除了
方法执行了0时间
最终通知,释放资源

this is afterReturning 方法

下面给出整个案例的结构图以及代码

17Spring_AOP编程(AspectJ)_AspectJ的注解编程
Myspect.java是切面类
//定义一个切面类。以及Advice方法
//这个注解表明这是切面类
@Aspect
public class Myspect {
//我们配置一个前置方法的Advice方法,这是一个Advice方法,当然要配置切点了
@Before("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))")
public void before1(JoinPoint joinPoint)
{
System.out.print("this is 前置方法");
}
//后置通知
@AfterReturning(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",returning="returnVal")
public void afterReturning(JoinPoint joinPoint,Object returnVal)
{
System.out.println("this is afterReturning 方法");
System.out.println(returnVal); } //环绕通知,在方法的前后执行,在工作中可以计算方法执行的时间,性能的监控,权限的设置,缓存的实行等
@Around("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
{
long begintime=System.currentTimeMillis();
Object result=proceedingJoinPoint.proceed();
long endtime=System.currentTimeMillis();
System.out.println("方法执行了"+(endtime-begintime)+"时间");
return result; }
@AfterThrowing(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",throwing="e")
public void afterThrowing(JoinPoint joinPoint,Exception e)
{
System.out.print(joinPoint.toLongString()+"方法发生了异常"+e.getMessage());
}
@After("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))")
public void after()
{
System.out.print("最终通知,释放资源"); } }

UserDao接口类:

public interface UserDao {
public int delete();
}

UserDao接口的实现类:

//编写目标类(真正被代理的)
public class UserDaoImpl implements UserDao { public int delete() {
System.out.println("删除了");
//int a=1/0;
return 1; } }

Junit测试类:

//JUnit与Spring的整合 (用注解)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml") public class TestMyspect {
@Autowired
private UserDao userDao; @Test
public void deletetest()
{
userDao.delete();
}
public void aroundTest()
{ userDao.delete();
}
}

ApplicationContext.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- AspectJ AOP --> <!-- 自动注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- xml配置目标bean和切面bean -->
<bean id="UserDao" class="com.guigu.shen.anotion.UserDaoImpl"></bean>
<bean id="Myspect" class="com.guigu.shen.anotion.Myspect"></bean> <!--
流程解释:
xml配置目标bean和切面bean,这样一来bean就会被加载,对象就创建好了,然后我们在之前不是配置了一个<aop:aspectj-autoproxy></aop:aspectj-autoproxy>了吗
这样就能给我们创建的UserDao和Myspect对象做代理了
--> </beans>