1.切面类的实现
切面类都是通过实现各种特定的接口来实现的,缺点是必须要实现特定的接口,且一个类基本上只有一个重写方法是有用的。
对于普通的类,若不实现特定的接口,可以通过可以通过注解转化为切面类(通知类)
2.注解的作用
@Aspect注解将此类定义为切面
@Before注解用于将目标方法配置为前置通知
@AfterReturning注解用于将目标方法配置为后置通知,在方法执行完毕后有返回值
@Around定义环绕通知
@AfterThrowing配置异常通知
@After也是后置通知,在方法执行完毕后没有返回值
3.关键代码
applicationContext.xml文件
<!-- 配置组件扫描器,在指定的基本包中扫描注解 -->
<context:component-scan base-package="com.xiaochen" />
<!-- 启动对@AspectJ注解的支持 -->
<aop:aspectj-autoproxy />
<!-- 为添加注解的myLog类创建一个Bean -->
<bean id="myLog" class="com.xiaochen.aop.MyLog" />
MyLog.java文件
//将此类定义为切面
@Aspect
public class MyLog
//将目标方法配置为前置通知
@Before("execution(* com.xiaochen.service.UserService.addUser())")
public void beforeMethod() {}
//将目标方法配置为后置通知
@AfterReturning("execution(* com.xiaochen.service.UserService.addUser())")
public void afterMethod() {}
应用实例:将一个普通类用注解转化为切面类
项目目录结构图
IUserDao.java
package com.xiaochen.dao;
public interface IUserDao {
public void addUser();
}
UserDaoImpl.java
package com.xiaochen.dao;
import org.springframework.stereotype.Component;
//使用注解方式定义一个Bean,其id为userDao
@Component("userDao")
public class UserDaoImpl implements IUserDao{
@Override
public void addUser() {
System.out.println("新增一个用户到数据库中");
}
}
UserService.java
package com.xiaochen.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import com.xiaochen.dao.IUserDao;
//使用注解方式定义Bean,其id为userService
@Component("userService")
public class UserService {
//使用注解注入在UserDaoImpl定义好的Bean
@Resource(name="userDao")
private IUserDao userDao;
//给域属性赋值
public void setUserDao(IUserDao userDao) {
this.userDao=userDao;
}
//调用IUserDao的addUser()方法
public void addUser() {
userDao.addUser();
}
}
Test.java
package com.xiaochen.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.xiaochen.service.UserService;
public class Test {
public static void main(String[] args) {
//1.加载配置文件
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
//2.从配置文件中获取Bean
UserService userService=(UserService)context.getBean("userService");
//3.使用Bean
userService.addUser();
}
}
MyLog
package com.xiaochen.aop;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import com.sun.istack.internal.logging.Logger;
//将此类定义为切面
@Aspect
public class MyLog {
private static final Logger log=Logger.getLogger(MyLog.class);
//将目标方法配置为前置通知
@Before("execution(* com.xiaochen.service.UserService.addUser())")
public void beforeMethod() {
log.info("使用注解实现通知,开始执行方法。。。");
}
//将目标方法配置为后置通知
@AfterReturning("execution(* com.xiaochen.service.UserService.addUser())")
public void afterMethod() {
log.info("使用注解实现通知,完成执行方法。。。");
}
}
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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置组件扫描器,在指定的基本包中扫描注解 -->
<context:component-scan base-package="com.xiaochen" />
<!-- 启动对@AspectJ注解的支持 -->
<aop:aspectj-autoproxy />
<!-- 为添加注解的myLog类创建一个Bean -->
<bean id="myLog" class="com.xiaochen.aop.MyLog" />
</beans>
log4j.properties
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.xiaochen=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
运行结果图