AOP
spring的IOC基于反射,通过读取配置文件获取对象的全限定类名,然后用反射创建,相当于是把BeanFactory包装了,扩展了。
而spring的AOP是基于动态代理,把动态代理包装起来,我们通过xml配置AOP使用,减少重复代码,减少程序耦合,帮助维护。
AOP术语
- 连接点(join-point):业务层中所有的方法都是连接点
- 切入点(point-cut):业务层中被增强的方法
- 通知(advice):拦截到连接点后要做的事情
- 前置通知:method.invoke前的东西
- 后置通知:method.invoke后的东西
- 异常通知:catch里的东西
- 最终通知:finally里的东西
- 环绕通知:整个invoke方法在执行时是环绕通知,在环绕通知中有明确的的切入点方法调用(metho.invoke())
- 目标对象(target):被代理对象
- 织入(weaving):代理的过程
- 代理(Proxy):产生的代理对象
- 切面(Aspect):切入点和通知的结合(就是你invoke方法里写的东西)
学习Spring中AOP要明确的事
开发阶段(我们做的):
- 编写核心业务:大部分程序员来做
- 把公共代码抽出来,制作成通知(开发阶段最后再做):AOP编程人员做
- 在配置文件中,声明切入点和通知的关系,即切面:AOP编程人员做
运行阶段(Spring框架完成的):
- Spring框架监控切入点方法的执行,一旦监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应功能织入,完成完整的代码逻辑运行。
spring中基于XML的AOP配置步骤
-
把业务层Bean和通知Bean交给spring管理
<bean id="accountService" class="com.chajiu.service.Impl.AccountService"></bean> <bean id="logger" class="com.chajiu.log.Logger"></bean>
-
使用
aop:config
标签表明开始AOP的配置 -
使用
aop:aspect
表明配置切面- id属性:给切面一个唯一标识
- ref属性:标识指定的通知类Bean的id
-
在
aop:aspect
标签内部使用各种通知类型的标签配置通知的类型 比如配置前置通知,使用:
asp:before
-
method
:用于指定通知类中的哪个方法是前置通知 -
pointcut
:用于指定切入点表达式,也就是指定切入点是哪个类的哪个方法。
-
-
aop:pointcut
可以把切入点单独拿出来,使用id
表示唯一名称,使用exception
指定表达式<aop:config> <aop:pointcut id="p1" expression="execution(* com.chajiu.service.Impl.*.*(..) )"/> <aop:aspect id="logAdvice" ref="logger"> <aop:before method="logSt" pointcut-ref="p1"></aop:before> <aop:after-returning method="logEd" pointcut-ref="p1"></aop:after-returning> </aop:aspect> </aop:config>
切入点表达式的写法:
-
关键字:execution(表达式)
-
表达式:
- 访问修饰符 返回值 包名.包名.包名.包名...类名.方法名(参数列表)
public void com.chajiu.service.impl.AccountServiceImpl.saveAccount()
-
访问修饰符可以省略
void com.chajiu.service.impl.AccountServiceImpl.saveAccount()
-
返回值可以使用通配符* 表示任意返回值
-
包名可以使用通配符* 表示任意包,但是有几级包写几个*
-
包名可以用
..
表示当前包及其子包* com..AccountServiceImpl.saveAccount()
-
类名和方法名都可以用
*
匹配(所以括号前通常是*.*
)* *..*.*()
-
参数列表
- 可以直接写数据类型
- 基本数据类型使用本身
int
- 引用类型需要全限定类名
java,lang,String
- 基本数据类型使用本身
- 可以使用*匹配任意数据类型,但是不能为空
- 使用
..
表示有无参数均可,有参数可以是任意参数
- 可以直接写数据类型
-
全通配写法
* *..*.*(..)
-
实际开发中切入点表达式通常写为:
- 业务层的所有方法
* com.chajiu.service.impl.*.*(..)
- 业务层的所有方法
网友评论