Spring aop 简单示例

简单的记录一下spring aop的一个示例

基于两种配置方式:

      基于xml配置

      基于注解配置

这个例子是模拟对数据库的更改操作添加事物

其实并没有添加,只是简单的输出了一下记录

首先看下整个例子的目录图

  Spring aop 简单示例

全部代码就不贴了,数目有点多,不过很简单,看一部分就能够明白

第一种配置方式

  基于xml方式配置

  首先将service,dao注册到spring容器

  Spring aop 简单示例

  配置一下扫描包还是很方便的

  接下来看下service

  

 package com.yangxin.core.service.impl;

 import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.yangxin.core.dao.UserDao;
import com.yangxin.core.pojo.User;
import com.yangxin.core.service.UserService; @Service
public class UserServiceImpl implements UserService { @Autowired
private UserDao userDao; @Override
public void addUser(User user) {
userDao.insertUser(user);
System.out.println("添加成功");
} @Override
public void deleteUser(String name) {
userDao.deteleUser(name);
System.out.println("删除成功");
} }

要做的事情很简单,插入一条数据,删除一条数据

接下来看下切面代码

 package com.yangxin.core.transaction;

 import org.aspectj.lang.ProceedingJoinPoint;

 import com.yangxin.core.pojo.User;

 public class TransactionDemo {

     //前置通知
public void startTransaction(){
System.out.println("begin transaction ");
} //后置通知
public void commitTransaction(){
System.out.println("commit transaction ");
} //环绕通知
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("begin transaction"); joinPoint.proceed(); System.out.println("commit transaction");
} }

然后看下这个切面在applicationContext.xml中是如何配置的

Spring aop 简单示例

 

 <aop:config>
<aop:pointcut expression="execution(* com.yangxin.core.service.*.*.*(..))" id="p1" /> <aop:aspect ref = "transactionDemo"> <aop:before method="startTransaction" pointcut-ref="p1" /> <aop:after-returning method="commitTransaction" pointcut-ref="p1"/> </aop:aspect>
</aop:config>

这里没有演示环绕通知

好了,运行测试代码

测试代码如下

   @Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/applicationContext.xml"); UserService userService = applicationContext.getBean(UserService.class); User user = new User(); user.setAge(19);
user.setName("yangxin"); userService.addUser(user);
userService.deteleUser("yangxin"); }

控制台输出如下

  begin transaction

  添加成功

  commit transaction

  begin transaction

  删除成功

  commit transaction

现在来测试一下环绕通知

修改一下applicationContext.xml中的配置切面那一部分

修改后的代码

 <aop:config>
<aop:pointcut expression="execution(* com.yangxin.core.service.*.*.*(..))" id="p1" /> <aop:aspect ref = "transactionDemo"> <aop:around method="around" pointcut-ref="p1"/> </aop:aspect>
</aop:config>

运行测试代码

输出如下

begin transaction
添加成功
commit transaction
begin transaction
删除成功
commit transaction

好了,现在贴下如何用注解的方法

贴下基于注解的切面的代码

 package com.yangxin.core.transaction;

 import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut; @Aspect
public class TransactionDemo2 { @Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")
public void point(){ } @Before(value="point()")
public void before(){
System.out.println("transaction begin");
} @AfterReturning(value = "point()")
public void after(){
System.out.println("transaction commit");
} @Around("point()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("transaction begin");
joinPoint.proceed();
System.out.println("transaction commit"); }
}

在applicationContext.xml中配置

 <bean id = "transactionDemo2" class = "com.yangxin.core.transaction.TransactionDemo2" />
 <aop:aspectj-autoproxy />

测试步骤和以上一致,这里就不贴了

完毕

记一下使用javaConfig配置方式的一些坑

以上 切面 不管是基于注解的还是基于xml配置的   这里把切面加载到容器中都是用xml配置bean的方式

如果用javaConfig方式的话

需要在配置类上加上 @EnableAspectJAutoProxy 注解

然后如果使用扫包的方式配置切面bean的话

切面上除了要加上@Aspect注解标识为这是一个切面bean之外

还需要在上面加上@component这个注解

很急很关键

排错的时候只关注切点表达式的问题了

当时一直在找切点表达式的问题

其实这个表达式写的是没有问题的

是配置切面bean的时候出的问题

深坑

上一篇:简单直白的去理解AOP,了解Spring AOP,使用 @AspectJ - 读书笔记


下一篇:Hibernate 延迟加载的代理模式 和 Spring AOP的代理模式