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 {
- @Override
- public void save() {
- System.out.println("book dao save...");
- }
-
- @Override
- public 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...
- 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.BookDaoImpl@b3ca52e
- 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.BookDaoImpl@7530ad9c
- class com.sun.proxy.$Proxy19
格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)
execution(public void com.example.dao.impl.BookDaoImpl.update(int))
通配符描述切入点:
- //匹配com.example包下任意包中的BookDao类或接口中所有update开头的带有一个参数的方法
- execution(public * com.example.*.BookDao.update*(*))
- //匹配com包下任意包中的BookDao类或接口中所有名称为update的方法
- execution(public Book com..BookDao.update(..))
execution(* *..*Dao+.*(..)) - @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...
- @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
- @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...
- //接口实现类的方法
- @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
- test
- @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 ret=null;
- try {
- ret= pjp.proceed();
- } catch (Throwable e) {
- e.printStackTrace();
- }
- return ret;
- }