代码改变世界

[译]在Java中使用JavaScript作为依赖注入容器

2012-12-30 21:14  fangzhao.lee  阅读(426)  评论(0编辑  收藏  举报

大多数Java开发人员是因为DI与AOP的需要而使用Spring的.Spring通常有冗长的XML配置.普通的JDK可以使用动态代理来处理AOP,这篇文章演示了使用JavaScript处理依赖注入.

Java 6起,Java应用程序可以在其JVM实例调用脚本语言,使用脚本API无缝地与脚本进行通信. Sun公司的JRE附带一个内置的引擎,通过这个API处理Javasript.我们可以利用Javascript的强大表现力JVM之执行一些很酷的东西.

我们要创建什么?

1.两个DAO接口和它们的模拟实现.

2.使用这些DAO的一个service示例.

3.JS脚本将它们连接到一起.

4.一个对service方法调用进行记录的简单拦截器.

DAO接口与实现:

package dao;

public interface BooksDAO {
    public int count();
}


package dao;

public interface MembersDAO {
    public int count();
}


package dao;

public class MockBooksDAO implements BooksDAO {

    @Override
    public int count() {
        return 500;
    }
}


package dao;

public class MockMembersDAO implements MembersDAO {

    @Override
    public int count() {
        return 100;
    }
}

 

Service接口与实现:

package service;

public interface LibraryService {

    public abstract int countBooks();

    public abstract int countMembers();

}


package service;

import dao.BooksDAO;
import dao.MembersDAO;

public class MockLibraryService implements LibraryService {
    private BooksDAO booksDAO;
    private MembersDAO membersDAO;

    public MockLibraryService(BooksDAO booksDAO, MembersDAO membersDAO) {
        this.booksDAO = booksDAO;
        this.membersDAO = membersDAO;
    }

    public int countBooks() {
        System.out.println("In countBooks()");
        return booksDAO.count();
    }

    public int countMembers() {
        System.out.println("In countMembers()");
        return membersDAO.count();
    }
}

 

依赖注入脚本:

我们利用JavaScript的Object直接量定义并组织DAOs与services.我们可以从应用程序中查找到这些以获得具体的实现.

src/objects.js

importPackage(Packages.dao)
importPackage(Packages.service)
importPackage(Packages.interceptor)

daos = {
 booksDAO : new MockBooksDAO(),
 membersDAO : new MockMembersDAO()
}

services = {
 libraryService : LoggingInterceptor.getProxy(new MockLibraryService(daos.booksDAO, daos.membersDAO))
}

 

应用程序代码:

我们使用ScriptEngineBuilder对Javacript求值,并从中获取service示例.

package app;

import javax.script.ScriptEngine;
import javax.script.ScriptException;

import service.LibraryService;
import util.ScriptEngineBuilder;

public class Main {
    public static void main(String[] args) throws ScriptException {
        ScriptEngine engine = new ScriptEngineBuilder("js").add("/objects.js").build();

        LibraryService service = (LibraryService) engine.eval("services.libraryService");

        System.out.println("Found " + service.countMembers() + " Members!");
        System.out.println("Found " + service.countBooks() + " Members!");
    }
}

 

添加AOP到组合中

创建JDK动态代理来记录所有方法调用

package interceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class LoggingInterceptor implements InvocationHandler {
    private Object target;

    public static Object getProxy(Object target) {
        ClassLoader loader = LoggingInterceptor.class.getClassLoader();
        Class[] interfaces = target.getClass().getInterfaces();
        InvocationHandler handler = new LoggingInterceptor(target);
        
        return Proxy.newProxyInstance(loader, interfaces, handler);
    }

    private LoggingInterceptor(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        try {
            System.out.println("Entered Method: " + method.getName());
            Object val = method.invoke(target, args);
            System.out.println("Completed Method: " + method.getName());
            return val;
        } catch (Exception e) {
            System.out.println("Exception in Method: " + method.getName());
            throw e;
        }
    }

}

现在,我们可以修改依赖注入脚本,利用代理改变service的创建方式

libraryService : LoggingInterceptor.getProxy(new MockLibraryService(daos.booksDAO, daos.membersDAO))

到此,我们有了一个非常好的干净的包含AOP的依赖注入配置方案,且不需要任何Java SE之外的东西.这里要记住的一个重点是,与使用注解不同,我们仍须在应用程序代码之外维护DIAOP的配置.Spring需要一卡车XML来达到同样的目的.

 

原文:http://blog.tuxychandru.com/2009/08/using-javascript-as-di-container-in.html