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(面向切面编程)简介 在我们平时的开发中,我们一般都是面对对象编程,面向对象的特点是继承.多态和封装,我们的业务逻辑代码主要是写在这一个个的类中,但我们在实现业务的同时,难免也到多个重复的操 ... 
随机推荐
- 《3+1团队》【Alpha】Scrum meeting 3
			项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 3+1团队 团队博客地址 https://home.cnblogs.com/u/3-1group ... 
- 通过洛谷P2639看01背包
			题目描述 Bessie像她的诸多姊妹一样,因为从Farmer John的草地吃了太多美味的草而长出了太多的赘肉.所以FJ将她置于一个及其严格的节食计划之中.她每天不能吃多过H ( <= H &l ... 
- HTML5新增的非主体元素header元素、footer元素、hgroup元素、adress元素
			---恢复内容开始--- header header元素是一种具有引导和导航作用的结构元素,通常用来放置整个页面或页面内的一个内容区块的标题,但是也可以包含其他内容,例如数据表格.搜索表单或相关的lo ... 
- ubuntu 宝塔安装一条龙服务
			ubuntu 安装 1, wget -O install.sh http://download.bt.cn/install/install-ubuntu.sh && sudo bash ... 
- CentOS 6.5 x64 安装MySql 5.6
			1.检测是否已经安装MySQL,输入以下命令 rpm -qa | grep mysql 如果存在,我们输入以下命令来删除 //强力删除 rpm -e --nodeps mysql 2.安装前环境准备 ... 
- 【HDU 1402】A * B Problem Plus(FFT)
			Problem Description Calculate A * B. Input Each line will contain two integers A and B. Process to e ... 
- str内部方法释义
			1. __add__:字符串拼接 [示例]:>>> str1=‘good’>>> str1.__add__(‘morning’)>>> ‘good ... 
- nginx启动、重启、关闭、升级
			一.启动 cd usr/local/nginx/sbin ./nginx 二.重启 更改配置重启nginx kill -HUP 主进程号或进程号文件路径 或者使用 cd /usr/local/ngin ... 
- Mysql学习总结(44)——Linux下如何实现mysql数据库每天自动备份定时备份
			概述 备份是容灾的基础,是指为防止系统出现操作失误或系统故障导致数据丢失,而将全部或部分数据集合从应用主机的硬盘或阵列复制到其它的存储介质的过程.而对于一些网站.系统来说,数据库就是一切,所以做好 ... 
- JustinMind
			看到公司老板新请来的兼职产品经理,在讲项目功能设计图是,用的是justinmind这个工具,觉得很好奇,默默记下,或许以后能用到.下面是搜的简单的介绍,只是为了记住这个工具名字,现并没有想要深入探究这 ... 
