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