企业网站的建立必要性,成都的建站公司,网站后台怎么添加图片,柚子皮wordpressAOP面向切面编程#xff0c;一种编程范式#xff0c;指导开发者如何组织程序结构
作用#xff1a;
在不惊动原始设计的基础上为其进行功能增强
核心概念
代理#xff1a;SpringAOP的核心本质是采用代理模式实现的连接点#xff1a;程序执行过程中的任意位置#xff0…AOP面向切面编程一种编程范式指导开发者如何组织程序结构
作用
在不惊动原始设计的基础上为其进行功能增强
核心概念
代理SpringAOP的核心本质是采用代理模式实现的连接点程序执行过程中的任意位置粒度为执行方法、抛出异常、设置变量等 在springAOP中理解为方法的执行切入点匹配连接点的式子 在springAOP中一个切入点可以只描述一个具体方法也可以匹配多个方法通知在切入点出执行的操作也就是共性功能在AOP中功能最终以方法的形式呈现通知类定义通知的类切面描述通知与切入点的对应关系
如果不理解的话可以看这一段话帮助理解连接点所有英雄、切入点增强的英雄、通知类buff库、通知各种buff、切面可以理解为设计师从buff库里面拿出具体的buff加强给英雄
现给一个入门案例
注解配置类
Configuration
ComponentScan(com.example)
EnableAspectJAutoProxy //切面相关注解
public class SpringConfig {
}
切面
Component //交给spring来管理
Aspect //声明这个类是切面
public class MyAdvice {//定义一个私有的切入点Pointcut(execution(void com.example.dao.BookDao.update()))private void pt(){}//通知在方法前执行Before(pt())public void method(){System.out.println(System.currentTimeMillis());}
}连接点及实现类
public interface BookDao {public void save();public void update();
}
Repository
public class BookDaoImpl implements BookDao {Overridepublic void save() {System.out.println(book dao save...);}Overridepublic void update() {System.out.println(book dao update...);}
}
测试
public class Aop {public static void main(String[] args) {ApplicationContext ctx new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao ctx.getBean(BookDao.class);bookDao.update();}
}
//输出
1712407510166
book dao update...
工作流程
Spring容器启动读取所有切面配置中的切入点初始化bean判定bean对应的类中的方法是否匹配到任意切入点 匹配失败创建对象 public static void main(String[] args) {ApplicationContext ctx new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao ctx.getBean(BookDao.class);//bookDao.update();System.out.println(bookDao);System.out.println(bookDao.getClass());}//输出
com.example.dao.impl.BookDaoImplb3ca52e
class com.example.dao.impl.BookDaoImpl 匹配成功创建原始对象(目标对象)的代理对象。目标对象原始功能去掉共性功能对应的类产生的对象这种对象是无法直接完成最终工作的。代理目标对象无法直接完成工作需要对其进行功能回调通过原始对象的代理对象实现 public static void main(String[] args) {ApplicationContext ctx new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao ctx.getBean(BookDao.class);//bookDao.update();System.out.println(bookDao);System.out.println(bookDao.getClass());}//输出
com.example.dao.impl.BookDaoImpl7530ad9c
class com.sun.proxy.$Proxy19 获取bean的执行方法 获取bean调用方法并执行完成操作获取的bean是代理对象时根据代理对象的运行模式运行原始方法与增强的内容完成操作
切入点表达式
切入点要进行增强的方法切入点表达式要进行增强的方法的描述方式
1. 描述方式
方式1执行com.example.dao包下的BookDao接口中的无参数update方法execution(void com.example.dao.BookDao.update())方式2执行com.example.dao.impl包下的BookDaoImpl类中的无参数update方法execution(void com.example.dao.impl.BookDaoImpl.update())
2. 切入点表达式的标准格式
格式动作关键字(访问修饰符 返回值 包名.类/接口名.方法名参数异常名)
execution(public void com.example.dao.impl.BookDaoImpl.update(int))
动作关键字描述切入点的动作行为例如execution表示执行到指定切入点访问修饰符public、private等可以省略返回值包名类/接口名方法名参数异常名方法定义中抛出指定异常可以省略
通配符描述切入点
* 单个独立的任意符号可以独立出现也可以作为前缀或者后缀的匹配出现 //匹配com.example包下任意包中的BookDao类或接口中所有update开头的带有一个参数的方法
execution(public * com.example.*.BookDao.update*(*)) .. 多个连续的任意符号可以独立出现常用于简化包名与参数的书写 //匹配com包下任意包中的BookDao类或接口中所有名称为update的方法
execution(public Book com..BookDao.update(..)) 专用于匹配子类型 execution(* *..*Dao.*(..))
通知类型
AOP通知描述了抽取的共性功能根据共性功能抽取的位置不同最终运行代码时要将其加入到合理的位置AOP通知共分为5种类型 前置通知Before Component //交给spring来管理
Aspect //声明这个类是切面
public class MyAdvice {//定义一个私有的切入点Pointcut(execution(void com.example.dao.BookDao.update()))private void pt(){}//通知在方法前执行Before(pt())public void method(){System.out.println(System.currentTimeMillis());}
}
//输出
1712407510166
book dao update... 后置通知After。如果方法异常也会执行 Component //交给spring来管理
Aspect //声明这个类是切面
public class MyAdvice {//定义一个私有的切入点Pointcut(execution(void com.example.dao.BookDao.update()))private void pt(){}After(pt())public void method(){System.out.println(System.currentTimeMillis());}
}//输出
book dao update...
1712407576367环绕通知Around Component //交给spring来管理
Aspect //声明这个类是切面
public class MyAdvice {//定义一个私有的切入点Pointcut(execution(void com.example.dao.BookDao.update()))private void pt(){}Around(pt())public void method(ProceedingJoinPoint pjp) throws Throwable {System.out.println(around before advice...);//表示对原始操作的调用pjp.proceed();//如果方法有返回值的话用以下//Object proceed pjp.proceed();System.out.println(around after advice...);}
}//输出
around before advice...
book dao update...
around after advice...注意事项 环绕通知必须依赖形参ProceedingJoinPoint才能实现对原始方法的调用进而实现原始方法调用前后同时添加通知通知中如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行对原始方法的调用可以不接收返回值通知方法设置成void即可如果接收返回值必须设定为Object类型原始方法的返回值如果是void类型通知方法的返回值类型可以设置成void也可以设置成Object类型由于无法预知原始方法运行后是否会抛出异常因此环绕通知方法必须抛出Throwable对象返回后通知AfterRunning。方法执行完后执行如果方法异常不会执行抛出异常后通知AfterThrowing。方法异常会执行无异常则不执行
通知获取数据
获取切入点方法的参数 JoinPoint适用于前置、后置、返回后、抛出异常后通知必须是第一个参数。现以前置为例 //接口实现类的方法
Override
public String findName(int id) {System.out.println(id:id);return test;
}//前置通知
//定义一个私有的切入点Pointcut(execution(* com.example.dao.BookDao.findName(..)))private void pt(){}Before(pt())public void before(JoinPoint joinPoint){//获取方法的参数Object[] args joinPoint.getArgs();System.out.println(Arrays.toString(args));System.out.println(before advice...);}//测试public static void main(String[] args) {ApplicationContext ctx new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao ctx.getBean(BookDao.class);String name bookDao.findName(100);System.out.println(name);}//输出
[100]
before advice...
id:100
testProceedingJoinPoint适用于环绕通知 Around(pt())public Object around(ProceedingJoinPoint pjp) throws Throwable {//获取方法的参数Object[] args pjp.getArgs();System.out.println(Arrays.toString(args));//可以对原始操作的参数进行修改args[0]666;Object proceed pjp.proceed(args);//args可加可不加默认是方法的参数修改后传递的是修改的数据return proceed;
}
//测试public static void main(String[] args) {ApplicationContext ctx new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao ctx.getBean(BookDao.class);String name bookDao.findName(100);System.out.println(name);}//输出
[100]
id:666
test 获取切入点方法返回值 返回后通知 AfterReturning(value pt(),returning ret)public void afterReturning(Object ret){System.out.println(方法的返回值是ret);System.out.println(afterReturning advice...);} 环绕通知。 Around(pt())public Object around(ProceedingJoinPoint pjp) throws Throwable {//获取方法的参数Object[] args pjp.getArgs();System.out.println(Arrays.toString(args));//可以对原始操作的参数进行修改args[0]666;Object proceed pjp.proceed(args);//args可加可不加默认是方法的参数修改后传递的是修改的数据return proceed;//proceed就是方法的返回值
}获取切入点方法运行异常信息 抛出异常后通知 AfterThrowing(value pt(),throwing t)public void afterThrowing(Throwable t){System.out.println(afterThrowing advice...);} 环绕通知。 Around(pt())public Object around(ProceedingJoinPoint pjp) throws Throwable {Object retnull;try {ret pjp.proceed();} catch (Throwable e) {e.printStackTrace();}return ret;}