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(面向切面编程)简介 在我们平时的开发中,我们一般都是面对对象编程,面向对象的特点是继承.多态和封装,我们的业务逻辑代码主要是写在这一个个的类中,但我们在实现业务的同时,难免也到多个重复的操 ...
随机推荐
- 字符串类型:str, bytes 的区别
Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分. 文本总是 Unicode,由 str 类型表示, 二进制数据则由 bytes 类型表示. Python 3不会以任意隐式的方 ...
- 数据库课程设计 PHP web实现
纪念一下自己写的东西.. 都说很垃圾就是了 直接用XAMPP做的 菜鸟网上学的PHP和HTML <!DOCTYPE html> <html> <head> < ...
- 开源代码生成器,基于mybatis-generator扩展,结合freemarker
git源码地址:https://github.com/JonSnow592622272/free-generator-code 码云gitee源码地址:https://gitee.com/a59262 ...
- Fiddler设置显式IP地址
打开Fiddler, 菜单栏:Rules->Customize Rules… 或快捷键 Ctrl+R . 通过快捷键 Ctrl+F ,搜索:static function Main() 函数. ...
- [BZOJ3940]:[Usaco2015 Feb]Censoring(AC自动机)
题目传送门 题目描述: FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过105的字符串S.他有一个包含n个单词的列表,列表里的n个单词记为t1…tN.他希望从S中删除这些单词.FJ每次在S中 ...
- 异常:java.lang.NoClassDefFoundError: org/springframework/expression/ParserContext
异常:java.lang.NoClassDefFoundError: org/springframework/expression/ParserContext 解决方案:缺少spring-expres ...
- Java会话(session)管理
会话概述 什么是会话 简单的理解:用户打开浏览器,点击多个超链接,访问Web服务器上多个资源,然后关闭浏览器,整个过程称之为一次会话. 需要解决的问题 每个用户在使用浏览器与服务器会话的过程中,会产生 ...
- struts2中关于jsp页面向action传值出现乱码问题
在JSP页面输入中文并传给后台的时候,常常会出现乱码问题,产生乱码的原因:java在进行传值的时候,默认用的是iso-8859-1的编码形式进行传输,而我们jsp页面常用的则是utf-8的编码形式.所 ...
- 【MyBatis】MyBatis Tomcat JNDI原理及源码分析
一. Tomcat JNDI JNDI(java nameing and drectory interface),是一组在Java应用中访问命名和服务的API,所谓命名服务,即将对象和名称联系起来,使 ...
- python 学习总结1
计算机与程序设计 一.计算机的概念 1.计算机是根据指令操作数据的设备. 2.计算机主要包括两个功能性一个是功能性另一个是计算性 功能性是对数据的操作,表现为数据计算,输入输出处理和结果存储 可编程性 ...