有没有专门帮人做图的网站,深圳网站制作联系兴田德润,seopc流量排名网站,山东省和住房建设厅网站首页注解开发AOP制作步骤#xff1a;
在XML格式基础上
导入坐标#xff08;伴随spring-context坐标导入已经依赖导入完成开启AOP注解支持配置切面Aspect定义专用的切入点方法#xff0c;并配置切入点Pointcut为通知方法配置通知类型及对应切入点Before 注解开发AOP注意事项
在XML格式基础上
导入坐标伴随spring-context坐标导入已经依赖导入完成开启AOP注解支持配置切面Aspect定义专用的切入点方法并配置切入点Pointcut为通知方法配置通知类型及对应切入点Before 注解开发AOP注意事项
切入点最终体现为一个方法无参无返回值无实际方法体内容但不能是抽象方法引用切入点时必须使用方法调用名称方法后面的不能省略切面类中定义的切入点只能在当前类中使用如果想引用其他类中定义的切入点使用“类名.方法名()”引用可以在通知类型注解后添加参数实现XML配置中的属性例如after-returning后的returning属性 AOP注解详解
Aspect 名称Aspect 类型注解 位置类定义上方 作用设置当前类为切面类 格式
Aspect
public class AopAdvice { }说明一个beans标签中可以配置多个aop:config标签
Pointcut 名称Pointcut 类型注解 位置方法定义上方 作用使用当前方法名作为切入点引用名称 格式 Pointcut(execution(* *(..)))public void pt() {}说明被修饰的方法忽略其业务功能格式设定为无参无返回值的方法方法体内空实现非抽象
Before 名称Before 类型注解 位置方法定义上方 作用标注当前方法作为前置通知 格式 Before(pt())public void before() {}特殊参数 无
After 名称After 类型注解 位置方法定义上方 作用标注当前方法作为后置通知 格式 After(pt())public void after() {}特殊参数 无
AfterReturning 名称AfterReturning 类型注解 位置方法定义上方 作用标注当前方法作为返回后通知 格式 AfterReturning(value pt(), returning ret)public void afterReturning(Object ret) {}特殊参数 returning 设定使用通知方法参数接收返回值的变量名
AfterThrowing 名称AfterThrowing 类型注解 位置方法定义上方 作用标注当前方法作为异常后通知 格式 AfterThrowing(value pt(), throwing t)public void afterThrowing(Throwable t) {}特殊参数 throwing 设定使用通知方法参数接收原始方法中抛出的异常对象名
Around 名称Around 类型注解 位置方法定义上方 作用标注当前方法作为环绕通知 格式 Around(pt())public Object around(ProceedingJoinPoint pjp) throws Throwable {Object ret pjp.proceed();return ret;}配置文件加载注解
public class AopPointcut {Pointcut(execution(* *..ABC(..)))public void pt(){}
}Before(AopPointcut.pt())public void before(){}AOP注解开发通知执行顺序控制
1.AOP使用XML配置情况下通知的执行顺序由配置顺序决定在注解情况下由于不存在配置顺序的概念的概念参照通知所配置的方法名字符串对应的编码值顺序可以简单理解为字母排序 同一个通知类中相同通知类型以方法名排序为准 不同通知类中以类名排序为准 使用Order注解通过变更bean的加载顺序改变通知的加载顺序
2.企业开发经验 通知方法名由3部分组成分别是前缀、顺序编码、功能描述 前缀为固定字符串例如baidu、itzhuzhu等无实际意义 顺序编码为6位以内的整数通常3位即可不足位补0 功能描述为该方法对应的实际通知功能例如exception、strLenCheck 制通知执行顺序使用顺序编码控制使用时做一定空间预留 003使用006使用预留001、002、004、005、007、008 使用时从中段开始使用方便后期做前置追加或后置追加 最终顺序以运行顺序为准以测试结果为准不以设定规则为准
AOP注解驱动 名称EnableAspectJAutoProxy 类型注解 位置Spring注解配置类定义上方 作用设置当前类开启AOP注解驱动的支持加载AOP注解 格式
Configuration
ComponentScan(com.itzhuzhu)
EnableAspectJAutoProxy
public class SpringConfig {
}AOP底层原理
静态代理动态代理——Proxy动态代理——CGLIB织入形式
静态代理
装饰者模式Decorator Pattern在不惊动原始设计的基础上为其添加功能
public class UserServiceDecorator implements UserService{private UserService userService;public UserServiceDecorator(UserService userService) {this.userService userService;}public void save() {//原始调用userService.save();//增强功能后置System.out.println(刮大白);}
}动态代理——JDK Proxy
JDKProxy动态代理是针对对象做代理要求原始对象具有接口实现并对接口方法进行增强
public class UserServiceJDKProxy {public UserService createUserServiceJDKProxy(final UserService userService){//获取被代理对象的类加载器ClassLoader classLoader userService.getClass().getClassLoader();//获取被代理对象实现的接口Class[] classes userService.getClass().getInterfaces();//对原始方法执行进行拦截并增强InvocationHandler ih new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//前置增强内容Object ret method.invoke(userService, args);//后置增强内容System.out.println(刮大白2);return ret;}};//使用原始被代理对象创建新的代理对象UserService proxy (UserService) Proxy.newProxyInstance(classLoader,classes,ih);return proxy;}
}动态代理——CGLIB
CGLIB(Code Generation Library)Code生成类库CGLIB动态代理不限定是否具有接口可以对任意操作进行增强CGLIB动态代理无需要原始被代理对象动态创建出新的代理对象可以动态生成字节码文件
public class UserServiceImplCglibProxy {public static UserServiceImpl createUserServiceCglibProxy(Class clazz){//创建Enhancer对象可以理解为内存中动态创建了一个类的字节码Enhancer enhancer new Enhancer();//设置Enhancer对象的父类是指定类型UserServerImplenhancer.setSuperclass(clazz);Callback cb new MethodInterceptor() {public Object intercept(Object o, Method m, Object[] a, MethodProxy mp) throws Throwable {Object ret mp.invokeSuper(o, a);if(m.getName().equals(save)) {System.out.println(刮大白);}return ret;}};//设置回调方法enhancer.setCallback(cb);//使用Enhancer对象创建对应的对象return (UserServiceImpl)enhancer.create();}
}代理模式的选择
Spirng可以通过配置的形式控制使用的代理形式默认使用jdkproxy通过配置可以修改为使用cglib
XML配置
!--XMP配置AOP--
aop:config proxy-target-classfalse/aop:configXML注解支持
!--注解配置AOP--
aop:aspectj-autoproxy proxy-target-classfalse/注解驱动
//注解驱动
EnableAspectJAutoProxy(proxyTargetClass true)综合案例
对项目进行业务层接口执行监控测量业务层接口的执行效率
public interface AccountService {void save(Account account);void delete(Integer id);void update(Account account);ListAccount findAll();Account findById(Integer id);
}案例分析 测量接口执行效率接口方法执行前后获取执行时间求出执行时长 System.currentTimeMillis( ) 对项目进行监控项目中所有接口方法AOP思想执行期动态织入代码 环绕通知 proceed()方法执行前后获取系统时间
案例制作步骤 定义切入点务必要绑定到接口上而不是接口实现类上 制作AOP环绕通知完成测量功能 注解配置AOP 开启注解驱动支持
案例制作核代码
Component
Aspect
public class RunTimeMonitorAdvice {//切入点监控业务层接口Pointcut(execution(* com.itzhuzhu.service.*Service.find*(..)))public void pt() {}Around(pt())public Object runtimeAround(ProceedingJoinPoint pjp) throws Throwable {//获取执行签名信息Signature signature pjp.getSignature();//通过签名获取执行类型接口名String className signature.getDeclaringTypeName();//通过签名获取执行操作名称方法名String methodName signature.getName();//执行时长累计值long sum 0L;for (int i 0; i 10000; i) {//获取操作前系统时间beginTimelong startTime System.currentTimeMillis();//原始操作调用pjp.proceed(pjp.getArgs());//获取操作后系统时间endTimelong endTime System.currentTimeMillis();sum endTime - startTime;}//打印信息System.out.println(className : methodName (万次run: sum ms);return null;}
}案例后续思考与设计 测量真实性 开发测量是隔离性反复执行某个操作是理想情况上线测量差异过大 上线测量服务器性能略低于单机开发测量 上线测量基于缓存的性能查询要优于数据库查询测量 上线测量接口的性能与最终对外提供的服务性能差异过大 当外部条件发生变化硬件需要进行回归测试例如数据库迁移 测量结果展示 测量结果无需每一个都展示需要设定检测阈值 阈值设定要根据业务进行区分一个复杂的查询与简单的查询差异化很大 阈值设定需要做独立的配置文件或通过图形工具配置工具级别的开发 配合图形界面展示测量结果