1.什么是AOP?
Aspect Orientied Programming 面向切面编程
在java EE中有OOA 面对对象分析 OOD 面对对象设计 OOP 面对对象编程
2.AOP涉及到核心概念
###Aspect 切面 抽取了共通业务逻辑的组件
JoinPoinr 连接点 切面作用的一个一个位置叫连接点 一般指的是方法
####Pointcut 切点 一堆连接点的集合 就是切点 后面会使用表达式来说明 就是后面的切点表达式的写法
Target 目标 将要增强功能的对象
Proxy 代理 增强之后的对象
(1) SUN 公司的 JDK代理 API proxy-target-class="false" servie
(2) CGLIB 的 动态代理API proxy-target-class="true" service的接口 iservice
###Advice 通知 ---- 调用的时机(目标方法调用之前 调用之后 调用前后 最终 和 异常)
切面 --- 通知 ---- 切点
3.实现AOP 的步骤
3.1.写一个Service 类 然后在配置文件 创建这个类对应的对象
这个Service 类中有 登录 和 注册的方法 里面输出 登录和注册的信息即可
<!--配置XdlUserService -->
<bean id="xdlUserService" class="com.xdl.service.XdlUserService">
</bean>
package com.xdl.service;
public class XdlUserService {
public void login() {
System.out.println("login......");
}
public void register() {
System.out.println("register....");
}
}
3.2.写一个切面类 要求在登录 和注册方法前输出 ******
package com.xdl.aspect;
public class XdlLogAspect {
public void log1() {
System.out.println("*********");
}
public void log2() {
System.out.println("$$$$$$$$$$");
}
}
3.3.配置切面类 到 登录 和 注册方法上
<!-- 配置切面对象 -->
<bean id="xdlLogAspect" class="com.xdl.aspect.XdlLogAspect">
</bean>
<aop:config>
<aop:aspect ref="xdlLogAspect">
<aop:before method="log1" pointcut="bean(xdlUserService)"/>
</aop:aspect>
</aop:config>
测试类:
public class XdlUserServiceTest {
public static void main(String[] args) {
ApplicationContext app =
new ClassPathXmlApplicationContext("applicationContext.xml");
XdlUserService userService = app.getBean("xdlUserService",XdlUserService.class);
userService.login();
}
}
输出:
配置切面前
配置切面后
4.切点表达式
4.1 bean限定表达式
bean(容器中组件的id) 容器中组件的id支持统配*
符合条件的bean对象中的所有方法 都会被切入共同逻辑
4.2类型限定表达式
within(包名.类型) 也支持通配*
例: <aop:before method="time" pointcut="within(com.xdl.service.XdlBankAccountService)"/>指定一个的
<aop:before method="time" pointcut="within(com.xdl.service.*)"/>统配service包下所有的类型
<aop:before method="time" pointcut="within(com.xdl..*)"/>xdl下以及子包所有的类型
4.3方法限定表达式
execution(权限修饰 返回值类型 方法名(参数列表) throws 异常)
返回值类型 方法名(参数列表)这些不能省略 不过可以使用统配
5.五种通知类型
<aop:before 目标方法调用之前 前置通知
<aop:after 目标方法调用之后 最终通知
目标方法即使出现异常 也会执行
<aop:after-returning 目标方法调用之后 后置通知
目标方出现异常 就不会执行
<aop:after-throwing 目标方法出现异常执行 异常通知
<aop:around 目标方法执行的前后都有执行 环绕通知
6.基于标注的AOP
6.1建立一个项目 导入jar包(ioc aop) 拷贝配置文件到src下
6.2在配置文件中开启组件扫描
6.3开发出 服务类 并在服务类加对应的 @Service 标注
6.4建立切面类 并在类上加 对应的 @Component 标注
6.5开启标注形式的 AOP
<aop:aspectj-autoproxy proxy-target-class="true" />
6.6在 切面类上加一个 @Aspect标注
方法上添加 @Before("切点表达式")
基本应用:
计算一个方法消耗的毫秒数,适合用around类型
@Around("within(com.xdl..*)")
public Object aRoundMethod(ProceedingJoinPoint pjp) throws Throwable {
long strat = System.currentTimeMillis();
//调用目标方法
Object object = pjp.proceed();
long end = System.currentTimeMillis();
System.out.println(pjp.getSignature()+":"+(end-strat));
return object;
}
ProceedingJoinPoint pjp 参数是连接点
pjp.getSignature() 获取签名 返回com.xdl.service.XdlBankAccountService
方法必须返回Object类型
使用@AfterThrowing来检查是哪个连接点上的方法发生了哪些异常并返回
@AfterThrowing(value="within(com.xdl..*)",throwing="e")
public void afterThrowingMethod(JoinPoint jp,Exception e) {
System.out.println(jp.getSignature()+"出现了"+e.getMessage()+"异常");
}
注意JoinPoint是org.aspectj包下的
结果:void com.xdl.service.XdlBankAccountService.login()出现了xixixi异常