Guice 学习(八)AOP (面向切面的编程)
Guice的AOP还是非常弱的。眼下只支持方法级别上的,另外灵活性也不是非常高。
看例如以下演示样例:
Guice支持AOP的条件是:
类必须是public或者package (default)
类不能是final类型的
方法必须是public,package或者protected
方法不能使final类型的
实例必须通过Guice的@Inject注入或者有一个无參数的构造函数
且看演示样例代码
1、定义接口
package com.guice.AOP;
import com.google.inject.ImplementedBy;
@ImplementedBy(ServiceImpl.class)
public interface Service {
public void sayHello();
}
2、定义实现类
package com.guice.AOP;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
@Singleton
public class ServiceImpl implements Service {
@Named("log")
@Override
public void sayHello() {
System.out.println(String.format("[%s#%d] execute %s at %d", this.getClass().getSimpleName(), hashCode(), "sayHello", System.nanoTime()));
}
}
3、定义切面
package com.guice.AOP;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* TODO :自己定义的方法拦截器。用于输出方法的运行时间
*
* @author E468380
*/
public class LoggerMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
String name = invocation.getMethod().getName();
long startTime = System.nanoTime();
System.out.println(String.format("before method[%s] at %s", name, startTime));
Object obj = null;
try {
obj = invocation.proceed();// 运行服务
} finally {
long endTime = System.nanoTime();
System.out.println(String.format("after method[%s] at %s, cost(ns):%d", name, endTime, (endTime - startTime)));
}
return obj;
}
}
4、測试类
package com.guice.AOP;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Names;
public class AopTest {
@Inject
private Service service;
public static void main(String[] args) {
Injector injector = Guice.createInjector(new Module() {
@Override
public void configure(Binder binder) {
binder.bindInterceptor(Matchers.any(), Matchers.annotatedWith(Names.named("log")), new LoggerMethodInterceptor());
}
});
injector.getInstance(AopTest.class).service.sayHello();
injector.getInstance(AopTest.class).service.sayHello();
injector.getInstance(AopTest.class).service.sayHello();
}
}
输出结果:
before method[sayHello] at 18832801981960
[ServiceImpl$$EnhancerByGuice$$d4244950#1109685565] execute sayHello at 18832817170768
after method[sayHello] at 18832817378285, cost(ns):15396325
before method[sayHello] at 18832817542181
[ServiceImpl$$EnhancerByGuice$$d4244950#1109685565] execute sayHello at 18832817640327
after method[sayHello] at 18832817781772, cost(ns):239591
before method[sayHello] at 18832817920651
[ServiceImpl$$EnhancerByGuice$$d4244950#1109685565] execute sayHello at 18832818013023
after method[sayHello] at 18832818132657, cost(ns):212006
关于此结果有几点说明:
(1)因为使用了AOP我们的服务得到的不再是我们写的服务实现类了,而是一个继承的子类,这个子类应该是在内存中完毕的。
(2)除了第一次调用比較耗时外(可能guice内部做了比較多的处理)。其他调用事件为0毫秒(我们的服务本身也没做什么事)。
(3)确实完毕了我们期待的AOP功能。
5、切面注入依赖
假设一个切面(拦截器)也须要注入一些依赖怎么办?
在这里我们声明一个前置服务。输出全部调用的方法名称。
①定义接口
package com.guice.AOP;
import org.aopalliance.intercept.MethodInvocation;
import com.google.inject.ImplementedBy;
@ImplementedBy(BeforeServiceImpl.class)
public interface BeforeService {
void before(MethodInvocation invocation);
}
②定义实现类
package com.guice.AOP;
import org.aopalliance.intercept.MethodInvocation;
public class BeforeServiceImpl implements BeforeService {
@Override
public void before(MethodInvocation invocation) {
System.out.println("Before--->" + invocation.getClass().getName());
}
}
③定义切面
package com.guice.AOP;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.google.inject.Inject;
//这个切面依赖前置服务
public class AfterMethodIntercepter implements MethodInterceptor {
@Inject
private BeforeService beforeService;
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
beforeService.before(invocation);
Object obj = null;
try {
obj = invocation.proceed();
} finally {
System.out.println("after--->" + invocation.getClass().getName());
}
return obj;
}
}
④编写測试类
package com.guice.AOP;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Names;
public class AopTest2 {
@Inject
private Service service;
public static void main(String[] args) {
Injector injector = Guice.createInjector(new Module() {
@Override
public void configure(Binder binder) {
AfterMethodIntercepter after = new AfterMethodIntercepter();
binder.requestInjection(after);
binder.bindInterceptor(Matchers.any(), Matchers.annotatedWith(Names.named("log")), after);
}
});
injector.getInstance(AopTest2.class).service.sayHello();
}
}
输出结果:
Before--->com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation
[ServiceImpl$$EnhancerByGuice$$618294e9#506575947] execute sayHello at 20140444543338
after--->com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation
说明
Binder绑定一个切面的API是:
com.google.inject.Binder.bindInterceptor(Matcher<? super Class<?
>>, Matcher<? super Method>, MethodInterceptor...)
第一个參数是匹配类,第二个參数是匹配方法,第三个数组參数是方法拦截器。也就是说眼下为止Guice只能拦截到方法,然后才做一些切面工作。
注意
虽然切面同意注入其依赖,可是这里须要注意的是。假设切面依赖仍然走切面的话那么程序就陷入了死循环,非常久就会堆溢出。
Guice的AOP还是非常弱的,眼下只支持方法级别上的。另外灵活性也不是非常高。
Guice 学习(八)AOP (面向切面的编程)的更多相关文章
- 学习笔记: AOP面向切面编程和C#多种实现
AOP:面向切面编程 编程思想 OOP:一切皆对象,对象交互组成功能,功能叠加组成模块,模块叠加组成系统 类--砖头 系统--房子 类--细胞 系统--人 ...
- AOP 面向切面的编程
一.面向切面的编程需求的产生 代码混乱:越来越多的非业务需求(日志和验证等)加入后,原有的业务方法急剧膨胀.每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点. 代码分散: 以日志需求为例,只是为了 ...
- spring框架学习(三)——AOP( 面向切面编程)
AOP 即 Aspect Oriented Program 面向切面编程 首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能. 所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务 ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存
代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...
- java aop面向切面编程
最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblog ...
- 浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~
简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring ...
- Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存
本文梯子 本文3.0版本文章 代码已上传Github+Gitee,文末有地址 大神反馈: 零.今天完成的深红色部分 一.AOP 之 实现日志记录(服务层) 1.定义服务接口与实现类 2.在API层中添 ...
- aop面向切面编程的实现
aop主要用于日志记录,跟踪,优化和监控 下面是来自慕课网学习的一些案例,复制黏贴就完事了,注意类和方法的位置 pom添加依赖: <dependency> <groupId>o ...
- AOP 面向切面编程, Attribute在项目中的应用
一.AOP(面向切面编程)简介 在我们平时的开发中,我们一般都是面对对象编程,面向对象的特点是继承.多态和封装,我们的业务逻辑代码主要是写在这一个个的类中,但我们在实现业务的同时,难免也到多个重复的操 ...
随机推荐
- c++类流操作运算符的重定义
对于流操作运算符我们需要注意的是函数的返回类型应该是流输入类型的引用或者流输出类型的引用,因为如果代码是 cout<<a<<b; 我们对a执行完cout函数之后,我们应该再次将 ...
- vue 指令---气泡提示(手撸实战)
菜鸟学习之路//L6zt github 自己在造组件轮子,也就是瞎搞.自己写了个slider组件,想加个气泡提示.为了复用和省事特此写了个指令来解决.预览地址项目地址 github 我叫给它胡博 cs ...
- spring-mvc jackson配置json为空不输出
使用的spring-mvc版本是4.1.6,jackson版本是2.1.4 在spring-mvc配置文件中添加以下代码就行 <mvc:annotation-driven> <mvc ...
- idea Error:(65, 27) java: 未结束的字符串文字
今天在使用IDEA的时候,出现了这个错误,原因项目文件编码不一致导致的,解决方法是: 将项目的文件编码全改成一致(UTF-8),如下图所示:
- 高可用技术之keepalived原理简单了解
Keepalived 工作原理 keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议. 虚拟路由冗余协 ...
- 【BZOJ 3555】 [Ctsc2014]企鹅QQ(哈希)
Description PenguinQQ是中国最大.最具影响力的SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志.群.即时通讯.相册.集市等丰富强大 ...
- POJ 3621 Sightseeing Cows (最优比率环 01分数划分)
题意: 给定L个点, P条边的有向图, 每个点有一个价值, 但只在第一经过获得, 每条边有一个花费, 每次经过都要付出这个花费, 在图中找出一个环, 使得价值之和/花费之和 最大 分析: 这道题其实并 ...
- 一份快速实用的 tcpdump 命令参考手册
对于 tcpdump 的使用,大部分管理员会分成两类.有一类管理员,他们熟知 tcpdump 和其中的所有标记:另一类管理员,他们仅了解基本的使用方法,剩下事情都要借助参考手册才能完成.出现这种情况 ...
- 儿子写日记 : " 夜深了,妈妈在打麻将,爸爸在上网……"
儿子写日记 : " 夜深了,妈妈在打麻将,爸爸在上网……" 爸爸检查时,很不满意地说 : " 日记源于生活,但要高于生活 !" ...
- zoj 2201 No Brainer
No Brainer Time Limit: 2 Seconds Memory Limit: 65536 KB Zombies love to eat brains. Yum. Input ...