写在前面
很久以前在有道云笔记上写的笔记,打算放弃它了,将笔记迁移到这里来。文章可能还有很多不足,请大家谅解,欢迎大佬提意见。
本文使用到的东西
- java
- ecplipse
- spring
aop概述
aop的原理基于java动态代理模式,在java文件夹中有动态代理示例
aop添加包
aop实现除了spring包以外还需要添加的包
链接:https://pan.baidu.com/s/1acjKuNkqxdwdoz1hghy_wg
提取码:tbko
aop简单示例
链接:https://pan.baidu.com/s/1ycVitoJJ0tHjexycTOnSGw
提取码:o48k
环绕通知中参数的一些运用示例
链接:https://pan.baidu.com/s/1rr-wNlNFaCnc4AMPgBeVUA
提取码:50jy
aop定义配置文件示例
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
">
<!-- 创建1个业务类对象 -->
<bean id="service" class="com.etc.service.UserServiceImpl">
</bean>
<!-- 创建1个业务类对象 -->
<bean id="service2" class="com.etc.service.UserServiceImpl2">
</bean>
<!-- 创建1个自定义通知类对象 -->
<bean id="advice" class="com.etc.advice.MyAdvice">
</bean>
<!-- 配置aop的织入-->
<aop:config>
<aop:pointcut expression="execution(* com.etc.service.UserService.*og*(..))" id="pc"/>
<aop:pointcut expression="execution(* com.etc.service.UserService.*eg*(..))" id="pc2"/>
<aop:aspect ref="advice">
<aop:before method="before" pointcut-ref="pc" /> <!-- 配置id为pc切点的前置织入-->
<aop:after method="after" pointcut-ref="pc2" /> <!-- 配置id为pc2切点的后置织入-->
<!--
<aop:before method="before" pointcut-ref="pc" />
<aop:after method="after" pointcut-ref="pc" />
<aop:around method="around" pointcut-ref="pc"/>
<aop:after-throwing method="afterthrow" pointcut-ref="pc"/>
-->
</aop:aspect>
</aop:config>
</beans>
aop标签介绍
<aop:config >标签
- 该标签用于配置aop的织入,里面写aop的具体实现
- 该标签在根标签中配置
<aop:pointcut >标签
使用示例:
<aop:pointcut expression="execution(* com.etc.service.UserService.*og*(..))" id="pc"/>
- 该标签用于添加aop切点,是<aop:config >的子标签,用于给指定的路径中的方法添加切点
- expression属性:用于设置切点的位置,填写格式如上,在包名前有一个“”号,和包名用空格隔开,包名中可以在任意位置添加“”,用来表示模糊查询
- id属性:给该切点设置一个id,在使用<aop:before >等标签时指定该id设置切点位置
<aop:aspect >标签
使用示例:
<aop:aspect ref="advice">
</aop:aspect>
- 该标签为<aop:config >的子标签,有<aop:before >等子标签
- 该标签用于指定通知的bean对象,该标签拥有<aop:before >等子标签,具体实现该通知对象切点的插入
- ref属性:要插入的自定义通知bean对象的id
<aop:before >、<aop:after >、<aop:around >、<aop:after-throwing >标签
使用示例:
<aop:after method="after" pointcut-ref="pc2" />
- <aop:before/ >:前置通知,在执行切点方法前执行指定方法
- <aop:after/ >:后置通知,在执行切点方法后执行指定方法
- <aop:around/ >:环绕通知,在指定执行方法中写执行语句执行切点方法
- <aop:after-throwing/ >:抛异常后通知,在程序运行抛出异常之后执行此方法
- 其他三个方法没有参数,环绕通知方法有一个ProceedingJoinPoint p参数
- 一个方法如果同时指定前置、后置和环绕通知,先执行前置通知、再执行环绕通知、最后执行后置通知
- method属性:填写其aop:aspect父标签指定的通知类中一个方法的名称,指定切点执行插入该方法
- pointcut-ref属性:指定一个</aop:aspect>切点id,表示在该切点执行method指定的方法
- 只有环绕通知能阻止原来代码的执行,实现新增权限管理。其他通知没有该功能
环绕通知执行切片方法
- p.proceed();就可以实现执行切片方法,并且可以多次使用p.proceed()执行
- p.getTarget()可以取得调用该方法的对象
- if (p.getTarget() instanceof UserServiceImpl) 判断p.getTarget()取得的是不是UserServiceImpl类的对象
p.proceed()示例:
public void around(ProceedingJoinPoint p)
{
System.out.println("这是环绕前通知!");
try {
p.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//执行原有的业务代码
System.out.println("这是环绕后通知!");
}
p.getTarget()示例:
public void around(ProceedingJoinPoint p)
{
//只有角色是admin才能删除帖子
if (p.getTarget() instanceof UserServiceImpl)
{
UserServiceImpl imp = (UserServiceImpl) p.getTarget();
if(!"admin".equals(imp.getRole()))
{
System.out.println("只有管理员才能删除帖子!");
return;
}
}
try {
p.proceed();//执行原有的代码
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//执行原有的业务代码
/*周日禁止注册
Calendar c = Calendar.getInstance(); //获取当前的日历
int day = c.get(Calendar.DAY_OF_WEEK);
if(day==Calendar.SUNDAY)
{
System.out.println("周四禁止注册!");
return;
}
*/
}