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还是很弱的,目前仅仅支持方法级别上的,另外灵活性也不是很高。

时间: 2024-10-20 17:24:51

Guice 学习(八)AOP (面向切面的编程)的相关文章

spring框架学习(三)——AOP( 面向切面编程)

AOP 即 Aspect Oriented Program 面向切面编程 首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能. 所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务 所谓的周边功能,比如性能统计,日志,事务管理等等 周边功能在Spring的面向切面编程AOP思想里,即被定义为切面 在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发 然后把切面功能和核心业务功能 "编织" 在一起,这就叫AOP 原理图 1. 功能分两大类,辅助功能和

spring学习之aop(面向切面编程)

AOP术语学习: Aspect:切面,封装用于横向插入系统功能(事务,日志)的类 Joinpoint:连接点,在程序执行过程中的某个阶段点 Pointcut:切入点,切面与程序流程的交叉点,即那些需要处理的连接点. Advice:在定义好的切入点所要执行的程序代码,可以理解为切面类中的方法. Target Object:通知的对象,如果aop采用的是动态aop实现,该对象就是一个被代理对象. Proxy:代理,将通知应用到目标对象之后,被动态创建的对象. Weaving:织入,将切面代码插入到目

java aop面向切面编程

最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming  面向切面编程.解耦是程序员编码开发过程中一直追求的.AOP也是为了解耦所诞生. 具体思想是:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回

浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring框架的,这就说明你有权选择是否要用AOP来完成一些业务. AOP面向切面编程,通过另一种思考的方式,来弥补面向对象编程OOP当中的不足,OOP当中最重要的单元是类,所以万物皆对象,万物皆是 对象类.而在AOP的模块单元中,最基础的单元是切面,切面对切点进行模块化的管理. 最后再提一句:Spring当

Javascript aop(面向切面编程)之around(环绕)

Aop又叫面向切面编程,其中“通知”是切面的具体实现,分为before(前置通知).after(后置通知).around(环绕通知),用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被严重忽视的技术点.但是利用aop可以有效的改善js代码逻辑,比如前端框架dojo和yui3中AOP则被提升至自定义事件的一种内在机制,在源码中随处可见.得益于这种抽象使得dojo的自定义事件异常强大和灵活.dojo中aop的实现在dojo/aspect模块中,主要有三个方法:before.after

sprint.net(2) AOP面向切面编程,spring.net的环绕通知;Spring.net的AOP通知的四种类型

AOP 有点类似于我们MVC里面的Filter过滤器,例如在MVC里面,如果给一个Action上打一个标签,就可以在这个Action执行之前或者之后,额外的执行一个方法,这个就相当于是面向切面编程. 无侵入式的. (也就是在不改变原来的代码的情况下,来跳转到一个其他的方法,执行完毕后回到主方法..),但是spring.net的AOP更牛叉,只需要在xml里面配置,就可以了,不需要在方法上面打特性的标签,也不需要继承什么类(例如MVC的过滤器是继承了ActionFilterAttribute) 主

什么是AOP面向切面编程

什么是AOP 连接地址:http://blog.csdn.net/moreevan/article/details/11977115/ AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关

AOP:面向切面编程

AOP:面向切面编程(Aspect-Oriented Programming)      AOP可以说是对OOP的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系.在OOP设计中,它导致了大量代码的重复,而不利于各个模块的

js实现面向切面的编程(AOP)

js实现面向切面的编程(AOP) 面向切面的编程(AOP) 还是有点意思的,可以在不修改原有代码的情况下增加新功能.有一些js框架实现AOP功能,但是有些时候我们并不能依赖于框架写程序(框架可能很笨重), 我们需要自己实现一些适合我们的功能模块.下面是我自己实现的js AOP,实现了before和after功能,仅供抛砖. 如下是aspect.js,是实现AOP的全过程. (function(window, undefined){  function aspect(type){   return