Aop
Aop(Aspect-Object Programmign面向切面编程)是Oop(Orientied-Object Programming)面向对象编程的延续;
面向过程----->面向对象------->面向切面
public interface UserDao{
public void add();
public void delete();
public void update();
}
public class UserDaoImpl implements UserDao{
public void add(){
System.out.println("添加");
}
public void delete(){
System.out.println("删除");
}
public void update(){
System.out.println("修改");
}
}
目前有一个需求:在不改变代码的时候,添加事务
第一种解决方法是编写目标类的子类,重写方法,完成需求,但是代码冗余,耦合度高,及其不方便。
上边是解决了问题,解决的不是很恰当,这时候就有了一种思想
动态代理思想(找人帮你做,不自己做了)
1.jdk代理:proxy代理对象,这种代理比较慢,以为过程是java–>字节码—>类,还有局限性,必须是接口和实现类同时存在
2.cglib(Code Generator Library他是基于asm字节码增强框架):快,没有局限性,有没有接口都可以,他是由字节码–>类
区别:jdk性能慢,jdk必须基于接口,cglib性能快,基于目标类子类
如何使用Spring框架完成Aop操作
1.必须掌握aop术语:
- 目标类:Target—>UserDaoImpl
- 链接点:JoinPoint—>是UserDaoImpl中没有添加通知的方法
- 切面类:Aspect 存储功能的类
- 通知/增强 :advice,切面类中的具体方法
- 切入点:PointCut—>是UserDaoImpl中添加通知的方法
- 代理类:Proxy 代理类
- 织入:weaving,将目标中的方法和通知放到代理类的过程
Spring是框架封装的一些功能
spring提供了切面类中的增强的类型
1.before前置通知:在目标方法前执行
2.after-Returning后置通知:在目标方法后执行
3.around环绕:前后都执行
4.after-Throwing:异常通知,有异常时候在通知
5.after:最终通知,无论如何都执行
有了增强类型,Spring框架应该放在哪
答:提供一个表达式叫切入点表达式
访问修饰符 包名.包名.包名.类名.方法名 (参数列表) 异常
execution("* com.oracle.daoImpl.*.* (..) ”)
execution("* com.oracle.daoImpl.*.* (int,int) ")
execution("* com.oracle.daoImpl.*.* (int,String)")
execution("* com.oracle.daoImpl.*Impl.* (int,String)")
execution("* com.oracle.daoImpl.*.*Impl (int,String)")
execution("* com.*.daoImpl.*.* (..) ")
SpringAop基于xml:
1.导入jar包
2.编写spring的配置文件
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 1.实例化 目标类 -->
<bean id="userDao" class="com.oracle.springAop.UserDaoImpl"></bean>
<!-- 2.实例化 切面类-->
<bean id="myAspect" class="com.oracle.springAop.Aspect"></bean>
<!-- 3.配置代理类 增强 ,如何放到目标方法上 -->
<aop:config>
<!-- 切面类 我们要将 切面类中的增强 放到 目标方法上 -->
<aop:aspect ref="myAspect">
<!-- 切入点表达式: -->
<aop:pointcut id="myPointCut"
expression="execution(* com.oracle.springAop.*.* (..))"/>
<!-- 切入点加 什么增强 啊 -->
<!-- 前置通知 -->
<!-- <aop:before method="before" pointcut-ref="myPointCut"></aop:before>-->
<!-- returning 方法的返回值 -->
<!--<aop:after-returning method="afterReturning" pointcut-ref="myPointCut" returning="obj"></aop:after-returning>-->
<!-- 环绕around -->
<aop:around method="around" pointcut-ref="myPointCut"></aop:around>
<!-- 异常通知 只有异常的时候才会执行-->
<aop:after-throwing method="afterThrowing" pointcut-ref="myPointCut" throwing="throwable"></aop:after-throwing>
<!-- 最终通知 -->
<aop:after method="after" pointcut-ref="myPointCut"></aop:after>
</aop:aspect>
</aop:config>
</beans>
public interface UserDao {
public void add();
public int delete(int id);
public void update();
}
/**
* 目标类:
*/
public class UserDaoImpl implements UserDao {
@Override
public void add() {
//int i = 1/0;
System.out.println("添加");
}
@Override
public int delete(int id) {
System.out.println("删除");
return id;
}
@Override
public void update() {
System.out.println("修改");
}
}
public class Aspect {
//1.前置通知
public void before(JoinPoint joinPoint){
//通过连接点 可以获取 基本信息
Signature signature = joinPoint.getSignature();
String name = signature.getName();
System.out.println("链接点的方法名: " + name);
//
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
System.out.println(arg);
}
System.out.println("开启事务");
}
//2.后置通知 afterReturning 必须有
public void afterReturning(Object obj){
System.out.println(obj); //返回的是方法参数值
System.out.println("关闭事务");
}
//3.环绕通知 around 1.元生jdk,2.spring 半自动, 3。spring全自动
// 4.spring Aop Aspectj ,5.注解
public Object around(ProceedingJoinPoint joinPoint){
Object obj = null;
try {
System.out.println("开启事务");
obj = joinPoint.proceed();// 跟 invoke(Object ,args); 用于执行目标方法
System.out.println("关闭事务");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return obj;
}
//4. 异常通知 只有出现异常的时候 才会执行
public void afterThrowing(Throwable throwable){
System.out.println("异常通知");
}
//5. 最终通知 after
public void after(){
System.out.println("最终通知");
}
}
SpringAop基于注解:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.oracle.AopAnnotation"/>
<context:annotation-config/>
<!-- 代理模式 proxy-target-class="false" jdk代理
proxy-target-class="true" cglib代理 -->
<aop:aspectj-autoproxy/>
</beans>
public interface UserDao {
public void add();
public int delete(int id);
public void update();
}
/**
* 目标类:
*/
public class UserDaoImpl implements UserDao {
@Override
public void add() {
//int i = 1/0;
System.out.println("添加");
}
@Override
public int delete(int id) {
System.out.println("删除");
return id;
}
@Override
public void update() {
System.out.println("修改");
}
}
package com.oracle.AopAnnotation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAspect {
//单独提取切入点表达式 公共的
@Pointcut(value = "execution(* com.oracle.AopAnnotation.*.* (..))")
public void pointcut(){}
//前置通知
// @Before(value = "pointcut()")
public void before(JoinPoint joinPoint){
System.out.println("开启事务");
}
//后置通知
// @AfterReturning(value = "pointcut()",returning = "obj")
public void afterReturning(Object obj){
System.out.println("目标方法的返回值: "+obj);
}
//
@Around(value = "pointcut()")
public Object around(ProceedingJoinPoint joinPoint){
Object object = null;
try {
//前置通知
before(joinPoint);
object = joinPoint.proceed(); //invoke返回对象
//后置通知
afterReturning(object);
} catch (Throwable throwable) {
//异常通知
afterThrowing(throwable);
}finally {
//最终通知
after();
}
return object;
}
//
// @AfterThrowing(value = "pointcut()",throwing = "e")
public void afterThrowing(Throwable e){
System.out.println("异常通知");
}
//
// @After(value = "pointcut()")
public void after(){
System.out.println("最终通知");
}
}