代理模式

对代理模式的理解,通过http://www.runoob.com/design-pattern/proxy-pattern.html

对AOP的代理模式,参考https://www.cnblogs.com/xujiming/p/5737531.html

目标:测试service层每一个方法的执行时间;

代理模式的本质:将被代理对象注入给代理对象,当调用代理对象时,实际上,是在调用被注入的被代理对象

理解:

代理对象 被代理对象
代理类 被代理对象
商家 厂商
房屋中介 房东

静态代理:代理类只有代理某一种类,不能代理任何一个类。

如何规范代理类和被代理类处理同样的业务?

让两个类实现相同的接口,这样同一个接口中的抽象方法就可以规范两个类实现相同的方法。

代码展示:

//该类是被代理类,实现了LoginServiceI 接口
@Service
public class LoginServiceImpl implements LoginServiceI { @Autowired
private LoginDaoI dao; @Override
public Boolean checkLogin(User user, HttpServletRequest request) {
Boolean flag = false;
User u = dao.checkLogin(user); if(u!=null){
request.getSession().setAttribute("userInfo", u);
flag = true;
}
return flag;
} @Override
public void getPower(HttpServletRequest request) throws IOException {
User u = (User) request.getSession().getAttribute("userInfo");
List<Power> list = dao.getPowerByUid(u);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(list);
request.setAttribute("json", json);
}
}

被代理类

//该类是代理类,实现了LoginServiceI 接口
@Service
public class LoginServiceProxy implements LoginServiceI { @Autowired
@Qualifier("loginServiceImpl")//防止注入失败报错
private LoginServiceI loginService; @Override
public Boolean checkLogin(User user, HttpServletRequest request) {
long t1 = System.currentTimeMillis();
Boolean flag = loginService.checkLogin(user, request);
long t2 = System.currentTimeMillis();
System.out.println(t2-t1+"ms");//计算出执行完成后的时间
return flag;
} @Override
public void getPower(HttpServletRequest request) throws IOException {
long t1 = System.currentTimeMillis();
loginService.getPower(request);
long t2 = System.currentTimeMillis();
System.out.println(t2-t1+"ms");//计算出执行完成后的时间
}
}

代理类

动态代理:(核心思想通过反射获取方法)代理类可以代理任何一个类。

JDK动态代理 :实现接口 InvocationHandler(java.lang.reflect.InvocationHanler反射包)  中的方法

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class TimeProxy implements InvocationHandler { //被代理对象
private Object obj; public TimeProxy(Object obj) {
this.obj = obj;
} //根据被代理对象生成代理对象
public Object createProxy() {
//Proxy.newProxyInstance(ClassLoader loader获取被代理对象的类加载器, Class<?>[] interfaces被代理对象所实现的接口, InvocationHandler h对象);
return Proxy.newProxyInstance(this.obj.getClass().getClassLoader(), this.obj.getClass().getInterfaces(), this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long t1 = System.currentTimeMillis();
Object result = method.invoke(this.obj, args);
long t2 = System.currentTimeMillis();
System.out.println(t2-t1);
return result;
} }

被代理类

在controller中调用

@Controller
public class LoginController { @Autowired
private LoginServiceI service; @RequestMapping("login")
@ResponseBody
public Boolean login(User user,HttpServletRequest request){
TimeProxy proxy = new TimeProxy(service);
LoginServiceI proxySerivce = (LoginServiceI) proxy.createProxy();
return proxySerivce.checkLogin(user,request);
}
}

在controller中调用被代理类

CGLib动态代理

通过AOP的切面实现——创建单独的类来进行管理。

package com.ggq.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.JoinPoint.StaticPart;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
//注解形式实现
@Component
@Aspect
public class TimeAspect { // 如果是SpringMvc 配置 在applicationContext.xml中添加配置 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
// 如果是SpringBoot 在启动类中加注解 @EnableAspectJAutoProxy//开启AspectJ注解
@Around("execution(* com.ggq.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint jp) throws Throwable {
long t1 = System.currentTimeMillis();
Object proceed = jp.proceed();
Signature signature = jp.getSignature();
System.out.println(signature);//User com.ggq.service.UserService.login(User)
StaticPart staticPart = jp.getStaticPart();
System.out.println(staticPart);//execution(User com.ggq.service.UserService.login(User))
Object target = jp.getTarget();
System.out.println(target);//com.ggq.service.impl.UserServiceImpl@7c82a93e
long t2 = System.currentTimeMillis();
System.out.println(t2-t1);
return proceed;
} @Before("execution(* com.ggq.service.*.*(..))")
public void beforeAdvice() {
System.out.println("this is 前置 advice");
} @After("execution(* com.ggq.service.*.*(..))")
public void afterAdvice() {
System.out.println("this is 最终 advice");
} @AfterReturning("execution(* com.ggq.service.*.*(..))")
public void afterReturingAdvice() {
System.out.println("this is 后置 advice");
} @AfterThrowing("execution(* com.ggq.service.*.*(..))")
public void afterThrowingAdvice() {
System.out.println("this is 异常 advice");
} }

如果不用注解@Component @Aspect @Around.......,可以再applicationContext.xml中配置标签

    <bean id="timeAspect" class="com.ggq.aspect.TimeAspect"></bean>

    <aop:config>
<aop:aspect ref="timeAspect">
<aop:pointcut expression="execution(* com.ggq.service.*.*(..))" id="pointcut"/>
<aop:around method="aroundAdvice" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>

工作中遇到测试执行时间的处理,如果再service中直接去计算,这样会造成不必要的输出,会影响日志,如果有计算,还会影响性能。
每个方法中有重复的代码,提高了代码的耦合度,不便于维护,所以可以通过AOP的切面来轻松实现。

个人意见,欢迎评论。

代理模式——用AOP测试业务层方法的执行时间的更多相关文章

  1. MVC5+EF6 简易版CMS(非接口) 第四章:使用业务层方法,以及关联表解决方案

    目录 简易版CMS后台管理系统开发流程 MVC5+EF6 简易版CMS(非接口) 第一章:新建项目 MVC5+EF6 简易版CMS(非接口) 第二章:建数据模型 MVC5+EF6 简易版CMS(非接口 ...

  2. Spring代理模式及AOP基本术语

    一.代理模式: 静态代理.动态代理 动态代理和静态代理区别?? 解析:静态代理需要手工编写代理类,代理类引用被代理对象. 动态代理是在内存中构建的,不需要手动编写代理类 代理的目的:是为了在原有的方法 ...

  3. Spring 代理模式及AOP基本术语

    一.代理模式: 静态代理.动态代理 动态代理和静态代理区别?? 解析:静态代理需要手工编写代理类,代理类引用被代理对象. 动态代理是在内存中构建的,不需要手动编写代理类 代理的目的:是为了在原有的方法 ...

  4. 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)

    好长时间没有用过Spring了. 突然拿起书.我都发现自己对AOP都不熟悉了. 其实AOP的意思就是面向切面编程. OO注重的是我们解决问题的方法(封装成Method),而AOP注重的是许多解决解决问 ...

  5. 代理模式与AOP

    代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联 ...

  6. 代理模式应用-AOP事务(转)

    https://jinnianshilongnian.iteye.com/blog/14872351.预备知识 aop概念请参考[http://www.iteye.com/topic/1122401] ...

  7. PowerMock+SpringMVC整合并测试Controller层方法

    PowerMock扩展自Mockito,实现了Mockito不支持的模拟形式的单元测试.PowerMock实现了对静态方法.构造函数.私有方法以及final方法的模拟支持,对静态初始化过程的移除等强大 ...

  8. 动态代理模式和AOP探究

    java强大的反射机制给动态代理带来了可能.能够自由穿梭在类与方法之间.简直神通广大. 动态代理的一个小例子,顺便看看神奇的AOP是如何实现的.代码如下: 首先声明的是一个接口Dog类 package ...

  9. Junit mockito 测试Controller层方法有Pageable异常

    1.问题 在使用MockMVC+Mockito模拟Service层返回的时候,当我们在Controller层中参数方法调用有Pageable对象的时候,我们会发现,我们没办法生成一个Pageable的 ...

随机推荐

  1. facebook分享

    http://bbs.mob.com/forum.php?mod=viewthread&tid=19104&page=1&extra=#pid40942  应用审核 http: ...

  2. tomcat 启动方式

    <?xml version="1.0" encoding="UTF-8"?><Context docBase="wexin" ...

  3. 腾讯云CDB回档失败浅析

    Ⅰ.先看问题 先简单介绍下cdb的回档功能,回档分为极速.快速.普通,分别对应指定表.指定库.整个实例回档. 控制台报错回档任务执行失败 提示信息:rollback table failed:SQL ...

  4. Jmeter post请求传参问题

    同线程组引用参数 举例1:新增数据bizId,然后将此次新增数据删除 添加新增数据接口,然后查询数据列表,正则表达式提取bizId 在删除接口引用此值${bizId} 添加断言,执行查看结果

  5. python之str字符串

    字符串是python非常重要的数据类型,它是一个序列(列表和元组也是序列),有下标,可以通过下标遍历字符串序列:同时字符串也是一个不可变数据类型,每次使用"+"拼接字符串时都会产生 ...

  6. Python 中文分词(结巴分词)

    特点: 支持三种分词模式: 精确模式,试图将句子最精确地切开,适合文本分析: 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义: 搜索引擎模式,在精确模式的基础上,对长词 ...

  7. 微信小程序区分点击,长按事件

    在上代码之前,微信小程序点击事件,长按事件的触发顺序需要我们了解一下下 事务分类 touchstart:手指触摸 longtap:手指触摸后后,超过350ms离开 touchend:手指触摸动作结束 ...

  8. VUE-002-前端分页(el-pagination)展示数据

    在web开发过程中,通常使用表格展示数据,在数据较多时采用分页的方式展示给用户. 分页方式有前端假分页和后端分页两种实现方式,此文仅记录前端假分页实现方式. 第一步:添加分页组件(el-paginat ...

  9. Asp.net 使用线程池实例

    实际开发经常会使用线程,如果每次使用都是创建线程.启动线程,然后销毁线程,从性能上来讲,非常占用系统开销,当线程达到一定量的时候会影响程序的运行和处理效率. 使用线程池:好处:线程池是一种多线程处理形 ...

  10. jeecg富文本编辑器增加字体(仿宋)

    jeecg富文本编辑器增加字体(仿宋) 温馨提示:jeecg 提供了 uedit 富文本的实现,如下针对的是 uedit 增加仿宋字体示例. 主要修改三个文件:plug-in\ueditor\uedi ...