[TOC]
# 定义通知
准备的类还是用UserServiceImpl
~~~
package aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
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 MyAdvice {
@Pointcut("execution(* service.*ServiceImpl.*(..))")
public void pc() {
}
// 前置通知
@Before("MyAdvice.pc()")
public void before(JoinPoint jp) {
// 使用前置通知可以完成日志记录,权限控制
System.out.println("拦截的目标类: " + jp.getSignature().getDeclaringTypeName());
System.out.println("拦截的方法名称: " + jp.getSignature().getName());
System.out.println("这是前置通知");
}
// 后置通知(如果出现异常不会调用)
@AfterReturning("execution(* service.*ServiceImpl.*(..))")
public void afterReturning(JoinPoint jp, Object val) {
// 第二个参数val它可以获取目标方法的返回值
// 注意:需要在配置文件中配置
// returning="val"
System.out.println("这是后置通知(如果出现异常不会调用)");
}
// 环绕通知
@Around("execution(* service.*ServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
// 可以完成日志操作,权限操作,性能监控,事务管理
System.out.println("这是环绕通知之前的部分");
// 调用目标方法
Object proceed = pjp.proceed();
System.out.println("这是环绕通知之后的部分");
return proceed;
}
// 异常通知
@AfterThrowing("execution(* service.*ServiceImpl.*(..))")
public void afterException() {
System.out.println("出现异常了");
}
// 后置通知(如果出现异常也会调用)
@After("execution(* service.*ServiceImpl.*(..))")
public void after(JoinPoint jp) {
System.out.println(jp.getSignature().getName());
System.out.println("这是后置通知(如果出现异常也会调用)");
}
}
~~~
# 导入约束
![](https://box.kancloud.cn/f4484c26a0813e16da39e5bd4c8acc19_1170x896.png)
![](https://box.kancloud.cn/b7ebcc92ede7df0c00e9e528fe9e856a_1328x1350.png)
![](https://box.kancloud.cn/d6a7ebc0ab8e6f6562b0314825f2c8e1_1046x696.png)
# 进行配置
~~~
<aop:config>来声明要对aop进行配置
<aop:pointcut>它是用于声明切点(简单说就是对哪些方法进行拦截)
<aop:advisor> 定义传统的aop的切面,传统的aop切面它只能包含一个切点与一个增强
<aop:aspect>定义aspectj框架的切面.,它可以包含多个切点与多个通知
~~~
~~~
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">
<!-- 准备工作: 导入aop(约束)命名空间 -->
<!-- 1.配置目标对象 -->
<bean name="userService" class="service.UserServiceImpl"></bean>
<!-- 2.配置通知对象 -->
<bean name="myAdvice" class="aspect.MyAdvice"></bean>
<!-- 3.配置将通知织入目标对象 -->
<aop:config>
<!-- 配置切入点
public void service.UserServiceImpl.save()
void service.UserServiceImpl.save()
* service.UserServiceImpl.save()
* service.UserServiceImpl.*()
* service.UserServiceImpl.*(..)
* service.*ServiceImpl.*(..)
* service..*ServiceImpl.*(..) //还会找子包
-->
<aop:pointcut expression="execution(* service.*ServiceImpl.*(..))" id="pc"/>
<aop:aspect ref="myAdvice">
<!-- 指定名为before方法为前置通知 -->
<aop:before method="before" pointcut-ref="pc" />
<!-- 后置通知(如果出现异常不会调用) -->
<aop:after-returning method="afterReturning" pointcut-ref="pc" returning="val" />
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pc" />
<!-- 异常拦截通知 -->
<aop:after-throwing method="afterException" pointcut-ref="pc" />
<!-- 后置 -->
<aop:after method="after" pointcut-ref="pc" />
</aop:aspect>
</aop:config>
</beans>
~~~
~~~
关于execution语法常用:
1. execution(public * *()) 所有的public的方法
2. execution(* cn.itheima.aop.*(..)) 所有的aop包下的所有类的方法(不包含子包)
3. execution(* cn.itheima.aop..*(..)) 所有的aop包及其子包下的所有类的方法
4. execution(* cn.itheima.aop.IOrderService.*(..)) IOrderService接口中定义的所有方法
5. execution(* cn.itheima.aop.IOrderService+.*(..)) 匹配实现特定接口所有类的方法
6. execution(* save*(..)) 区配所有的以save开头的方法
~~~
# 测试
~~~
//帮我们创建容器
@RunWith(SpringJUnit4ClassRunner.class)
// 指定创建容器时使用那个配置文件
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
@Resource(name = "userService")
private UserService us;
@Test
public void fun1() {
us.save();
}
}
~~~
# 使用注解
需要改下配置文件
~~~
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">
<!-- 准备工作:导入aop(约束)命名空间 -->
<!-- 1.配置目标对象 -->
<bean name="userService" class="service.UserServiceImpl"></bean>
<!-- 2.配置通知对象 -->
<bean name="myAdvice" class="aspect.MyAdvice"></bean>
<!-- 3.开启使用注解完成织入,开启aspectJ注解自动代理功能 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
~~~
然后MyAdvice类
~~~
package aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
//通知类
//表示该类是一个通知类
@Aspect
public class MyAdvice {
// 前置通知
@Before("execution(* service.*ServiceImpl.*(..))")
public void before() {
System.out.println("这是前置通知");
}
// 后置通知(如果出现异常不会调用)
@AfterReturning("execution(* service.*ServiceImpl.*(..))")
public void afterReturning() {
System.out.println("这是后置通知(如果出现异常不会调用)");
}
// 环绕通知
@Around("execution(* service.*ServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
/**
* 环绕通知内部一定要确保执行该方法,如果不执行该方法,业务bean中被拦截的方法就不会被执行。
* 当执行该方法,如果后面还有切面的话,它的执行顺序应该是这样的:先执行后面的切面,如果后面没有切面了,
* 再执行最终的目标对象的业务方法。若不执行该方法,则后面的切面,业务bean的方法都不会被执行。
*/
System.out.println("这是环绕通知之前的部分");
// 调用目标方法
Object proceed = pjp.proceed();
System.out.println("这是环绕通知之后的部分");
return proceed;
}
// 异常通知
@AfterThrowing("execution(* service.*ServiceImpl.*(..))")
public void afterException() {
System.out.println("出现异常了");
}
// 后置通知(如果出现异常也会调用)
@After("execution(* service.*ServiceImpl.*(..))")
public void after() {
System.out.println("这是后置通知(如果出现异常也会调用)");
}
}
~~~
其他一样
我们可以再把一些东西抽出来
~~~
@Pointcut("execution(* service.*ServiceImpl.*(..))")
public void pc() {
}
// 前置通知
@Before("MyAdvice.pc()")
public void before() {
System.out.println("这是前置通知");
}
~~~
使用@Pointcut注解定义切点
在每一个通知中定义切点,工作量大,不方便维护,我们可以使用@Pointcut来声明切点
切点允许逻辑运算例如`mypointcut()||mypointcut1`
![](https://box.kancloud.cn/e746c9eda8af7bd5ab225b03ad68940c_1008x624.png)
- 基础
- 编译和安装
- scanner类(键盘录入)
- Random类(随机数)
- 数组
- 方法
- 类
- ArrayList集合
- char与int
- eclipse
- IDEA
- 变量与常量
- 常用API
- String,StringBuffer,StringBuilder
- 正则,Date,DateFormat,Calendar
- 包装类,System,Math,Arrays,BigInteger,BigDecimal
- 集合,迭代器,增强for,泛型
- List,set,判断集合唯一
- map,Entry,HashMap,Collections
- 异常
- IO
- File
- 递归
- 字节流
- 字符流
- IO流分类
- 转换流
- 缓冲流
- 流的操作规律
- properties
- 序列化流与反序列化流
- 打印流
- commons-IO
- IO流总结
- 多线程
- 线程池
- 线程安全
- 线程同步
- 死锁
- lock接口
- ThreadLoad
- 等待唤醒机制
- 线程状态
- jdbc
- DBUtils
- 连接池DBCP
- c3p0连接池
- 网络编程
- 多线程socket上传图片
- 反射
- xml
- 设计模式
- 装饰器模式
- web service
- tomcat
- Servlet
- response
- request
- session和cookie
- JSP
- EL
- JSTL
- 事务
- 监听器Listener
- 过滤器Filter
- json
- linux安装软件
- 反射详解
- 类加载器和注解
- 动态代理
- jedis
- Hibernate
- 简介
- 创建映射文件
- Hibernate核心配置文件
- 事务和增删改查
- HibernateUtils
- 持久化对象的三种状态
- 检索方式
- query
- Criteria
- SQLQuery
- 持久化类
- 主键生成策略
- 缓存
- 事务管理
- 关系映射
- 注解
- 优化
- struts2
- 搭建
- 配置详解
- Action
- 结果跳转方式
- 访问ServletAPI方式
- 如何获得参数
- OGNL表达式
- valueStack 值栈
- Interceptor拦截器
- spring
- 导包
- IOC和DI
- Bean获取与实例化
- Bean属性注入
- spring注解
- 注解分层
- junit整合
- aop
- 动态代理实现
- cglib代理实现
- aop名词
- spring的aop
- aop-xml详解
- aop-注解详解
- 代理方式选择
- jdbcTemplate
- spring事务管理
- 回滚注意
- 事务传播属性
- MyBatis
- MyBatis简介
- 入门程序
- 与jdbc hibernate不同
- 原始Dao开发
- Mapper动态代理方式
- SqlMapConfig.xml配置文件
- 输入参数pojo包装类
- resultMap
- 动态sql
- 一对一关联
- 一对多
- 整合spring
- 逆向工程
- maven
- maven简介
- 仓库
- maven目录结构
- maven常用命令
- 生命周期
- eclipse中maven插件
- 入门程序
- 整合struct
- 依赖范围
- 添加插件
- idea配置
- jar包冲突
- 分模块开发
- 构建可执行的jar包(包含依赖jar包)
- springMVC
- 处理流程
- java面试
- java版本升级
- java1-8版本变更
- java9新特性
- 锁
- java资料
- idea
- jdk版本切换
- log4j
- 入门实例
- 基本使用方法
- Web中使用Log4j
- spring中使用log4j
- java代码优化