AOP的annotation实现方式是基于AspectJ的实现

AOP的annotation实现方式是基于AspectJ的实现,需要以下几步:

首先,需要添加AspectJ的包:aspectjrt.jar aspectweaver.jar

其次,在applicationContext .xml文件中添加配置,否则不能使用aspectj的语法,在此之前,需要在引入AOP的命名空间xmlns:aop=http://www.springframework.org/schema/aop

再次,添加切面类

@Aspect

@Component

public class LogInterceptor {

@Before(“execution(public void com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

public void beforeMethod(){

   System.out.println("method before");

}

@After(“execution(public void com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

public void afterMethod(){

   System.out.println("method after");

}

@AfterReturning(“execution(public * com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

public void afterReturning(){

   System.out.println("method after returning");

}

@AfterThrowing(“execution(public * com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

public void afterThrowing(){

   System.out.println("method throws exception");

}

@Around(“execution(public * com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

public void around(ProceedingJoinPoint pjp) throws Throwable{

   System.out.println("method around start");

   pjp.proceed();

   System.out.println("method around end");

}

}

@Before(“execution(public void com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

这句话的意思是:在执行类com.bjsxt.dao.impl.UserDAOImpl中的任何类型的参数,任何返回值为空,访问类型为public的方法之前都会执行beforeMethod()方法。

@AfterThrowing(“execution(public * com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

这句话所定义的通知是在所调用的函数抛出异常的时候才会调用

@AfterReturning(“execution(public * com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

这句话所定义的通知是在所调用的函数正常返回的时候才会调用

@After(“execution(public void com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

这句话定义的通知在程序返回之后(包括正常返回和抛出异常返回)会调用

@Around(“execution(public * com.bjsxt.dao.impl.UserDAOImpl.*(..))”)

around通知需要一个ProceedingJoinPoint 类型的参数pjp,并且在程序中需调用pjp.proceed();

User实体类:

public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

UserDAO的内容:

public interface UserDAO {
public void save(User user);
}

UserDAOImpl的内容:

@Component(“userDAOImpl”)
public class UserDAOImpl implements UserDAO {
public void save(User user) {
System.out.println(“user saved!”);
}
}

UserService的内容:

@Component(“userService”)
public class UserService {

private UserDAO userDAO;
public UserDAO getUserDAO() {
return userDAO;
}
@Resource(name=”userDAOImpl”)
public void setUserDAO( UserDAO userDAO) {
this.userDAO = userDAO;
}
public void add(User user) {
userDAO.save(user);
}
}

测试类的内容(使用Junit测试):

public class UserServiceTest {
@Test
public void testAdd() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(“beans.xml”);
UserService service = (UserService)ctx.getBean(“userService”);
service.add(new User());
}

}

最后,直接执行即可,运行结果:

method around start

method before

user saved!

method around end

method after

method after returning

通过观察不难发现,每个通知后面的切入点语法都是一样的,因此,此时可以定义一个切入点,然后不同的通知直接调用即可

@Aspect

@Component

public class LogInterceptor {

@Pointcut("execution(public * com.bjsxt.dao..*.*(..))")

public void myMethod(){}

@Before("myMethod()")

public void beforeMethod(){

   System.out.println("method before");

}

@After("myMethod()")

public void afterMethod(){

   System.out.println("method after");

}

@AfterReturning("myMethod()")

public void afterReturning(){

   System.out.println("method after returning");

}

@AfterThrowing("myMethod()")

public void afterThrowing(){

   System.out.println("method throws exception");

}

@Around("myMethod()")

public void around(ProceedingJoinPoint pjp) throws Throwable{

   System.out.println("method around start");

   pjp.proceed();

   System.out.println("method around end");

}

}

运行程序,结果相同:

method around start

method before

user saved!

method around end

method after

method after returning

原文地址:https://www.cnblogs.com/lllini/p/11955360.html