1.引入spring基础包
2.引入aspectJ的jar包:
com.springsource.org.aopalliance-*.jar
com.springsource.org.aspectj.weaver-*.jar
3.实现目标类UserDAO
@Repository("userDao")
public class UserDao {
//添加用户
public void addUser(){
System.out.println("添加用户");
}
//删除用户
public void deleteUser(){
System.out.println("删除用户");
}
}
4.定义前面类MyAspect
public class MyAspect {
//定义切入点
@Pointcut("execution(* com.aspect.*.*(..))")
//使用一个返回值为void、方法体为空的方法来命名切入点
private void myPointCut(){}
//前置通知
@Before("myPointCut()")
public void myBefore(JoinPoint joinPoint) {
System.out.println("前置通知”模拟执行权限检查.....,");
System.out.println("目标类是:" + joinPoint.getTarget());
System.out.println(",被植入增强处理的目标方法为:" + joinPoint.getSignature().getName());
}
//后置通知
@AfterReturning("myPointCut()")
public void myAfterReturning(JoinPoint joinPoint) {
System.out.println("后置通知:模拟记录检查日志....,");
System.out.println("被植入增强处理目标类方法为:" + joinPoint.getSignature().getName());
}
//环绕通知
@Around("myPointCut()")
public Object myAroud(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//开始
System.out.println("环绕开始:执行目标方法之前,模拟开启事务...");
//执行当前目标方法
Object obj = proceedingJoinPoint.proceed();
//结束
System.out.println("环绕结束:执行目标方法之后,模拟关闭事务...");
return obj;
}
//异常通知
@AfterThrowing(value = "myPointCut()",throwing = "e")
public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println("异常通知:" + "出错了" + e.getMessage());
}
//最终通知
@After("myPointCut()")
public void myAfter() {
System.out.println("最终通知:模拟方法结束后的释放资源....");
}
}
5.bean2.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-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:annotation-config/>
<!--指定需要扫描的包,使注解生效-->
<context:component-scan base-package="com.aspect.annotation"/>
<!--启动基于注解的声明式AspectJ支持-->
<aop:aspectj-autoproxy />
</beans>
6.测试类test
public class test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean2.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
//执行方法
userDao.addUser();
}
}
7.实现的效果
前置通知模拟执行权限检查.....,
目标类是:com.aspect.UserDao@29626d54
,被植入增强处理的目标方法为:addUser
环绕开始:执行目标方法之前,模拟开启事务...
添加用户
最终通知:模拟方法结束后的释放资源....
环绕结束:执行目标方法之后,模拟关闭事务...
后置通知:模拟记录检查日志....,
被植入增强处理目标类方法为:addUser
备注:
@Aspect 定义切面类
@Componet 将这个类加入Spring的IOC容器;
切入点表达式execution(* com.aspect.* .*(..))
第一个 * 号:表示返回类型, * 号表示所有的类型。
第二个 * 号:表示类名
(* 与 包后面有一个空格,要不然会报错)
括号里面表示方法的参数,两个句点表示任何参数。
通知类型
@Before 前置通知,在方法执行之前执行
@After 后置通知,在方法执行之后执行
@AfterRunning 返回通知,在方法返回结果之后执行
@AfterThrowing 异常通知,在方法抛出异常之后执行
@Around 环绕通知,围绕着方法执行
实现AOP,目标(target)类就需生成动态代理。注意:
1、目标类如果实现了某一个接口,那么Spring就会利用JDK类库生成动态代理。
2、目标类没有实现某一个接口,那么Spring就会利用CGLIB类库直接修改二进制码来生成动态代理,需要引用CGLIB类库