做经营网站怎么赚钱吗,关于做网站的合同,ios开发者选项,查询关键词AOP切面编程
通知类型表达式重用表达式切面优先级使用注解开发#xff0c;加上注解实现某些功能
简介
动态代理分为JDK动态代理和cglib动态代理当目标类有接口的情况使用JDK动态代理和cglib动态代理#xff0c;没有接口时只能使用cglib动态代理JDK动态代理动态生成的代理类…AOP切面编程
通知类型表达式重用表达式切面优先级使用注解开发加上注解实现某些功能
简介
动态代理分为JDK动态代理和cglib动态代理当目标类有接口的情况使用JDK动态代理和cglib动态代理没有接口时只能使用cglib动态代理JDK动态代理动态生成的代理类会在com.sun.proxy包下类名为$proxy1和目标类实现相同的接口cglib动态代理动态生成的代理类会和目标在在相同的包下会继承目标类动态代理InvocationHandlerJDK原生的实现方式需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口兄弟两个拜把子模式。cglib通过继承被代理的目标类认干爹模式实现代理所以不需要目标类实现接口。AspectJ是AOP思想的一种实现。本质上是静态代理将代理逻辑“织入”被代理的目标类编译得到的字节码文件所以最终效果是动态的。weaver就是织入器。Spring只是借用了AspectJ中的注解。
依赖
!--spring context依赖--
!--当你引入Spring Context依赖之后表示将Spring的基础依赖引入了--
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion6.0.2/version
/dependency!--spring aop依赖--
dependencygroupIdorg.springframework/groupIdartifactIdspring-aop/artifactIdversion6.0.2/version
/dependency
!--spring aspects依赖--
dependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion6.0.2/version
/dependency注解说明
Aspect表示这个类是一个切面类Component注解保证这个切面类能够放入IOC容器
简单使用
几种通知类型
前置通知Before()环绕通知Around()返回通知AfterReturning()异常通知AfterThrowing()后置通知After()
表达式介绍 切入点表达式
在方法中可以传入参数public void afterMethod(JoinPoint joinPoint)类型为JoinPoint 获取连接点的签名信息 String methodName joinPoint.getSignature().getName()获取目标方法的返回值 其中表达式中returning后面参数result要与public void afterReturningMethod(JoinPoint joinPoint, Object result)传入参数名称一样类型可以不一样但是名称要一样。 AfterReturning(value execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..)), returning result)
public void afterReturningMethod(JoinPoint joinPoint, Object result){String methodName joinPoint.getSignature().getName();System.out.println(Logger--返回通知方法名methodName结果result);
}获取目标方法的异常 在表达式中加入throwing ex和上面一样传入参数名称要一直也要是ex如Throwable ex AfterThrowing(value execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..)), throwing ex)
public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex){String methodName joinPoint.getSignature().getName();System.out.println(Logger--异常通知方法名methodName异常ex);
}切入点表达式使用
前置通知
Aspect// 表示这个类是一个切面类
Component// 注解保证这个切面类能够放入IOC容器
public class LogAspect {// 设置切入点和通知类型Before(value execution(public int com.example.aop.annoaop.CalculatorImpl.*(..)))public void beforeMethod(JoinPoint joinPoint) {Object[] args joinPoint.getArgs();System.out.println(Logger--前置通知 参数 args[0] , args[1]);}
}后置通知
Aspect// 表示这个类是一个切面类
Component// 注解保证这个切面类能够放入IOC容器
public class LogAspect {After(value execution(public int com.example.aop.annoaop.CalculatorImpl.*(..)))public void afterMethod(JoinPoint joinPoint) {String name joinPoint.getSignature().getName();// 方法名System.out.println(Logger--后置通知方法名 name);}
}返回通知
Aspect// 表示这个类是一个切面类
Component// 注解保证这个切面类能够放入IOC容器
public class LogAspect {AfterReturning(value execution(public int com.example.aop.annoaop.CalculatorImpl.*(..)), returning result)public void afterReturn(JoinPoint joinPoint, Object result) {String methodName joinPoint.getSignature().getName();System.out.println(Logger--返回通知方法名 methodName 结果 result);}
}异常通知
Aspect// 表示这个类是一个切面类
Component// 注解保证这个切面类能够放入IOC容器
public class LogAspect {AfterThrowing(value execution(public int com.example.aop.annoaop.CalculatorImpl.*(..)), throwing ex)public void afterThrowingMethod(JoinPoint joinPoint, Exception ex) {String methodName joinPoint.getSignature().getName();System.out.println(Logger--异常通知方法名 methodName 异常 ex);}
}环绕通知
Aspect// 表示这个类是一个切面类
Component// 注解保证这个切面类能够放入IOC容器
public class LogAspect {Around(value execution(public int com.example.aop.annoaop.CalculatorImpl.*(..)))public Object aroundMethod(ProceedingJoinPoint joinPoint) {String methodName joinPoint.getSignature().getName();String args Arrays.toString(joinPoint.getArgs());Object result null;try {System.out.println(环绕通知--目标对象方法执行之前);// 目标对象连接点方法的执行result joinPoint.proceed();System.out.println(环绕通知--目标对象方法返回值之后);} catch (Throwable throwable) {throwable.printStackTrace();System.out.println(环绕通知--目标对象方法出现异常时);} finally {System.out.println(环绕通知--目标对象方法执行完毕);}return result;}
}重用切入点表达式
申明表达式
Pointcut(execution(* com.atguigu.aop.annotation.*.*(..)))
public void pointCut(){}在方法中使用
Before(pointCut())
public void beforeMethod(JoinPoint joinPoint){String methodName joinPoint.getSignature().getName();String args Arrays.toString(joinPoint.getArgs());System.out.println(Logger--前置通知方法名methodName参数args);
}在不同切面中使用
Before(com.atguigu.aop.CommonPointCut.pointCut())
public void beforeMethod(JoinPoint joinPoint){String methodName joinPoint.getSignature().getName();String args Arrays.toString(joinPoint.getArgs());System.out.println(Logger--前置通知方法名methodName参数args);
}切面的优先级
相同目标方法上同时存在多个切面时切面的优先级控制切面的内外嵌套顺序。
优先级高的切面外面优先级低的切面里面
使用Order注解可以控制切面的优先级
Order(较小的数)优先级高Order(较大的数)优先级低
将Order注解放在切面类上而不是方法上
优先级低的
Aspect// 表示这个类是一个切面类
Component// 注解保证这个切面类能够放入IOC容器
Order(4)
public class LogAspect {After(value pointcut())public void afterMethod2(JoinPoint joinPoint) {String name joinPoint.getSignature().getName();// 方法名System.out.println(Logger--后置通知 111111方法名 name);}
}优先级高的
Aspect// 表示这个类是一个切面类
Component// 注解保证这个切面类能够放入IOC容器
Order(1)
public class NewLogAspect {After(value com.example.aop.annoaop.LogAspect.pointcut())public void afterMethod(JoinPoint joinPoint) {String name joinPoint.getSignature().getName();// 方法名System.out.println(Logger--后置通知 444444方法名 name);}
}效果
原先交换顺序后 没有交换顺序前 注解使用
使用AOP在方法或者接口上写上某些注解完成特定方法。
实现思路
创建interface和上面一样要写Aspect并且要被spring管理在方法或者接口上加上interface注解
实现示例
创建interface 并命名为BunnyLog
Retention(RetentionPolicy.RUNTIME)
Target({ElementType.METHOD, ElementType.TYPE})
// 加上这个注解打印当前时间
public interface BunnyLog {}使用AOP切面需要注意的是 如果只是单纯的加上注解不考虑指定类或者类中方法完成某些功能要修改下面切入点 Pointcut(value annotation(com.example.aop.annoaop.BunnyLog))
public void bunnyPointcut() {
}如果想指定某些类或者某些方法下的 Pointcut(execution(* com.example.aop.annoaop.*.*(..)) annotation(com.example.aop.annoaop.BunnyLog))
public void bunnyPointcut() {
}创建切面
Aspect
Component
public class BunnyAspect {/*** 切入点并且加上了 BunnyLog注解*/Pointcut(value execution(* com.example.aop.annoaop.*.*(..)) || annotation(com.example.aop.annoaop.BunnyLog))public void bunnyPointcut() {}Before(bunnyPointcut())public void before(JoinPoint joinPoint) {String name joinPoint.getSignature().getName();System.out.println(------AOP前置通知生效方法名称------ name);LocalDateTime localDateTime LocalDateTime.now();DateTimeFormatter timeFormatter DateTimeFormatter.ofPattern(yyy年MM月dd日 HH:mm:ss);String format localDateTime.format(timeFormatter);System.out.println(BunnyAspect现在时间 format);}
}普通方法需要在类上加上Component被spring管理之后再方法中加上注解BunnyLog
Component
public class BunnyTestImpl {BunnyLogpublic void method() {LocalDateTime localDateTime LocalDateTime.now();DateTimeFormatter timeFormatter DateTimeFormatter.ofPattern(yyy年MM月dd日 HH:mm:ss);String format localDateTime.format(timeFormatter);System.out.println(测试方法现在时间 format);}
}创建一个测试类
public class TestBefore {Testpublic void test1() {ApplicationContext context new ClassPathXmlApplicationContext(bean.xml);BunnyTestImpl bean context.getBean(BunnyTestImpl.class);bean.method();}
}执行结果 r); System.out.println(“测试方法现在时间” format); } } - 创建一个测试类java
public class TestBefore {Testpublic void test1() {ApplicationContext context new ClassPathXmlApplicationContext(bean.xml);BunnyTestImpl bean context.getBean(BunnyTestImpl.class);bean.method();}
}执行结果