资讯专栏INFORMATION COLUMN

慕课网_《使用Google Guice实现依赖注入》学习总结

2450184176 / 2517人阅读

摘要:时间年月日星期六说明本文部分内容均来自慕课网。慕课网教学源码学习源码第一章课程介绍课程简介是啥读音是轻量级的依赖注入框架说明一个的框架需要有基础什么是剥离注入轻量级代码少易维护性能优异,跟比较。

时间:2017年10月14日星期六
说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com
教学源码:https://github.com/zccodere/s...
学习源码:https://github.com/zccodere/s...

第一章:课程介绍 1-1 课程简介

Google Guice:Guice是啥

Guice读音:juice
Guice is a lightweight dependency injection framework for java
Guice 是轻量级的依赖注入框架

Google Guice:说明

Java:一个java的框架、需要有java基础
dependency injection:什么是dependency、剥离dependency、注入dependency
lightweight:轻量级(代码少、易维护、性能优异),跟Spring比较。
但是:学习曲线陡峭、对开发者的要求太高了

课程目标

理解、重新理解dependency injection
掌握Guice的语法,更要掌握Guice的设计理念
开始在你的下一个项目中使用Guice

课程要点

什么是Guice
dependency injection:改造Hello World程序
注入(Injection)
绑定(Binding)
作用域或生命周期(Scope)
Guice AOP
使用Guice和SpringBoot协作搭建一个简单的Web应用
Guice vs Spring
1-2 产生原因

Spring的不足

手动配置:使用xml进行配置,配置太过庞大
自动配置:Spring提供了自动配置,复杂项目无法实现

Guice不同于Spring

取消xml
取消bean的概念
使用Constructor来注入
泛型支持
一个专注于Dependency Injection的框架

参考资料

https://github.com/google/guice/wiki/Motivation
https://github.com/google/guice/wiki/ExternalDocumentation
更多利用英文资料,如Stackoverflow
第二章:理解依赖 2-1 基础配置

Hello Guice

配置Guice环境
Dependency Injection基础
改造Hello World

创建名为guicedemo的maven工程pom如下


    4.0.0

    com.myimooc
    guicedemo
    0.0.1-SNAPSHOT
    jar

    guicedemo
    http://maven.apache.org

    
        UTF-8
        1.8
        1.8
        1.8
    

    
        
            com.google.inject
            guice
            4.1.0
        
        
            com.google.inject.extensions
            guice-multibindings
            4.1.0
        
        
        
            junit
            junit
            4.12
            test
        
    

2-2 依赖分析

经典Hello World分析

核心算法:将指定内容输出至指定目标

改造Hello World程序

面向对象化
消除Dependency
用Guice来配置Dependency
2-3 面向对象

代码编写

1.编写MyApplet类

package com.myimooc.guicedemo;

/**
 * @title Applet类
 * @describe 提供run()方法
 * @author zc
 * @version 1.0 2017-10-15
 */
public interface MyApplet extends Runnable{
    
}

2.编写HelloWorldPrinter类

package com.myimooc.guicedemo.helloworlddemo;

import com.myimooc.guicedemo.MyApplet;

/**
 * @title HelloWorldPrinter类
 * @describe 提供打印HelloWorld的功能
 * @author zc
 * @version 1.0 2017-10-15
 */
public class HelloWorldPrinter implements MyApplet {
    
    private void printHelloWorld() {
        System.out.println("Hello World!");
    }
    
    @Override
    public void run() {
        printHelloWorld();
    }
}

3.编写Configuration类

package com.myimooc.guicedemo;

import com.myimooc.guicedemo.helloworlddemo.HelloWorldPrinter;

/**
 * @title Configuration类
 * @describe 程序启动配置类
 * @author zc
 * @version 1.0 2017-10-15
 */
public class Configuration {
    
    public static MyApplet getMainApplet() {
        return new HelloWorldPrinter();
    }
    
}

4.编写App类

package com.myimooc.guicedemo;

/**
 * @title 启动类
 * @describe 改造HelloWorld类
 * @author zc
 * @version 1.0 2017-10-15
 */
public class App {
    /**
     * main方法的作用
     * bootstrap:
     *   parse command line:解析命令行参数
     *   set up environment:配置环境参数
     *   kick off main logic:启动程序逻辑
     * @param args
     */
    public static void main(String[] args) {
        MyApplet mainApplet = Configuration.getMainApplet();
        mainApplet.run();
    }
}

面向对象化小结

善于运用IDE提供的重构能力
    Ctrl + 1:猜测下一步动作
    Ctrl + shift + r:重命名
    先写代码,再让其编译通过
    先思考确定需要什么,然后再机械性劳动实现
函数命名
    从实现角度:精确描述函数干什么
    从调用者角度:描述调用者需求
    两者不匹配:需要进行抽象的点
2-4 提取依赖

代码编写

1.编写MyApplet类

package com.myimooc.guicedemo.noguice;

/**
 * @title MyApplet类
 * @describe 提供run()方法
 * @author zc
 * @version 1.0 2017-10-15
 */
public interface MyApplet extends Runnable{
    
}

2.编写StringWritingApplet类

package com.myimooc.guicedemo.noguice.helloworlddemo;

import com.myimooc.guicedemo.noguice.MyApplet;

/**
 * @title HelloWorldPrinter类
 * @describe 提供打印HelloWorld的功能
 * @author zc
 * @version 1.0 2017-10-15
 */
public class StringWritingApplet implements MyApplet {
    
    private MyDestination destination;
    private StringProvider stringProvider;
    
    public StringWritingApplet(MyDestination destination,StringProvider stringProvider) {
        super();
        this.destination = destination;
        this.stringProvider = stringProvider;
    }

    private void writeString() {
        destination.write(stringProvider.get());
    }
    
    @Override
    public void run() {
        writeString();
    }
}

3.编写StringProvider类

package com.myimooc.guicedemo.noguice.helloworlddemo;

/**
 * @title StringProvider类
 * @describe 提供get()方法
 * @author zc
 * @version 1.0 2017-10-15
 */
public interface StringProvider {

    String get();

}

4.编写MyDestination类

package com.myimooc.guicedemo.noguice.helloworlddemo;

/**
 * @title MyDestination类
 * @describe 提供write()方法
 * @author zc
 * @version 1.0 2017-10-15
 */
public interface MyDestination {

    void write(String string);

}

5.编写PrintStreamWriter类

package com.myimooc.guicedemo.noguice.helloworlddemo;

import java.io.PrintStream;

/**
 * @title PrintStreamWriter类
 * @describe 实现write()方法
 * @author zc
 * @version 1.0 2017-10-15
 */
public class PrintStreamWriter implements MyDestination {

    private PrintStream destination;
    
    public PrintStreamWriter(PrintStream destination) {
        super();
        this.destination = destination;
    }

    @Override
    public void write(String string) {
        destination = System.out;
        destination.println(string);
    }
}

6.编写Configuration类

package com.myimooc.guicedemo.noguice;

import com.myimooc.guicedemo.noguice.helloworlddemo.PrintStreamWriter;
import com.myimooc.guicedemo.noguice.helloworlddemo.StringProvider;
import com.myimooc.guicedemo.noguice.helloworlddemo.StringWritingApplet;

/**
 * @title Configuration类
 * @describe 程序启动配置类
 * @author zc
 * @version 1.0 2017-10-15
 */
public class Configuration {
    
    public static MyApplet getMainApplet() {
        return new StringWritingApplet(
               new PrintStreamWriter(System.out),
               new StringProvider() {
                    @Override
                    public String get() {
                        return "Hello World";
                    }
                });
    }
}

7.编写App类

package com.myimooc.guicedemo.noguice;

/**
 * @title 启动类
 * @describe 改造HelloWorld类
 * @author zc
 * @version 1.0 2017-10-15
 */
public class App {
    /**
     * main方法的作用
     * bootstrap:
     *   parse command line:解析命令行参数
     *   set up environment:配置环境参数
     *   kick off main logic:启动程序逻辑
     * @param args
     */
    public static void main(String[] args) {
        MyApplet mainApplet = Configuration.getMainApplet();
        mainApplet.run();
    }
}

消除Dependency小结

2-5 配置依赖

代码编写

1.编写MyApplet类

package com.myimooc.guicedemo.useguice;

/**
 * @title MyApplet类
 * @describe 提供run()方法
 * @author zc
 * @version 1.0 2017-10-15
 */
public interface MyApplet extends Runnable{
    
}

2.编写StringWritingApplet类

package com.myimooc.guicedemo.useguice.helloworlddemo;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.myimooc.guicedemo.useguice.MyApplet;

/**
 * @title HelloWorldPrinter类
 * @describe 提供打印HelloWorld的功能
 * @author zc
 * @version 1.0 2017-10-15
 */
public class StringWritingApplet implements MyApplet {
    
    private MyDestination destination;
    private Provider stringProvider;
    
    @Inject
    public StringWritingApplet(MyDestination destination,@Output Provider stringProvider) {
        super();
        this.destination = destination;
        this.stringProvider = stringProvider;
    }

    private void writeString() {
        destination.write(stringProvider.get());
    }
    
    @Override
    public void run() {
        writeString();
    }
}

3.编写MyDestination类

package com.myimooc.guicedemo.useguice.helloworlddemo;

/**
 * @title MyDestination类
 * @describe 提供write()方法
 * @author zc
 * @version 1.0 2017-10-15
 */
public interface MyDestination {

    void write(String string);

}

4.编写PrintStreamWriter类

package com.myimooc.guicedemo.useguice.helloworlddemo;

import java.io.PrintStream;

import javax.inject.Inject;

/**
 * @title PrintStreamWriter类
 * @describe 实现write()方法
 * @author zc
 * @version 1.0 2017-10-15
 */
public class PrintStreamWriter implements MyDestination {

    private PrintStream destination;
    
    @Inject
    public PrintStreamWriter(PrintStream destination) {
        super();
        this.destination = destination;
    }

    @Override
    public void write(String string) {
        destination = System.out;
        destination.println(string);
    }
}

5.编写Output类

package com.myimooc.guicedemo.useguice.helloworlddemo;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import com.google.inject.BindingAnnotation;

/**
 * @title Output注解
 * @describe 
 * @author zc
 * @version 1.0 2017-10-15
 */
@Retention(RetentionPolicy.RUNTIME)
@BindingAnnotation
public @interface Output {

}

6.编写HelloWorldModule类

package com.myimooc.guicedemo.useguice.helloworlddemo;

import java.io.PrintStream;

import com.google.inject.AbstractModule;
import com.myimooc.guicedemo.useguice.MyApplet;

/**
 * @title HelloWorldModule类
 * @describe HelloWorld模块的依赖配置
 * @author zc
 * @version 1.0 2017-10-15
 */
public class HelloWorldModule extends AbstractModule{
    
    @Override
    protected void configure() {
        bind(MyApplet.class).to(StringWritingApplet.class);
        bind(MyDestination.class).to(PrintStreamWriter.class);
        bind(PrintStream.class).toInstance(System.out);
        bind(String.class).annotatedWith(Output.class).toInstance("Hello World");
    }
}

7.编写MainModule类

package com.myimooc.guicedemo.useguice;

import com.google.inject.AbstractModule;
import com.myimooc.guicedemo.useguice.helloworlddemo.HelloWorldModule;

/**
 * @title MainModule类
 * @describe Guice用来配置的类
 * @author zc
 * @version 1.0 2017-10-15
 */
public class MainModule extends AbstractModule{

    @Override
    protected void configure() {
        install(new HelloWorldModule());
    }
}

8.编写App类

package com.myimooc.guicedemo.useguice;

import com.google.inject.Guice;

/**
 * @title 启动类
 * @describe 改造HelloWorld类
 * @author zc
 * @version 1.0 2017-10-15
 */
public class App {
    /**
     * main方法的作用
     * bootstrap:
     *   parse command line:解析命令行参数
     *   set up environment:配置环境参数
     *   kick off main logic:启动程序逻辑
     * @param args
     */
    public static void main(String[] args) {
        MyApplet mainApplet = Guice
                .createInjector(new MainModule())
                .getInstance(MyApplet.class);
        mainApplet.run();
    }
}

Guice配置Dependency小结

第三章:注入依赖 3-1 基本注入

注入图解

注入(Injection)

构造函数注入
    使用final来区分dependency和状态
    注入时不考虑如何实现或绑定
成员变量注入
    用于测试
    使用injectMembers来注入测试用例

代码编写

1.编写OrderService类

2.编写PaymentService类

3.编写PriceService类

4.编写OrderServiceImpl类

5.编写PaymentServiceImpl类

6.编写PriceServiceImpl类

7.编写SessionManager类

8.编写ServerModule类

9.编写OrderServiceTest类

受篇幅限制,源码请到我的github地址查看

3-2 其他注入

注入Provider

如何注入Provider

DatabaseConnection dbConn
Provider< DatabaseConnection > dbConnProvider
Guice会考虑对象生命周期
需要时可以自己实现Provider

命名注入

@Inject @Named(“dbSpec”) private String dbSpec;
@Inject @LogFileName private String logFileName;
使用@Named:参数来自配置文件或命令行、或者为了开发方便
使用属性:通常采用此方法

代码编写

1.修改SessionManager类

package com.myimooc.guicedemo.server.impl;

import javax.inject.Inject;

import com.google.inject.Provider;

/**
 * @title session管理类
 * @describe 模拟订单系统
 * @author zc
 * @version 1.0 2017-10-15
 */
public class SessionManager {
    
    private final Provider sessionIdProvider;
    
    @Inject
    public SessionManager(@SessionId Provider sessionIdProvider) {
        super();
        this.sessionIdProvider = sessionIdProvider;
    }

    public Long getSessionId() {
        return sessionIdProvider.get();
    }

}

2.修改ServerModule类

package com.myimooc.guicedemo.server.impl;

import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.myimooc.guicedemo.server.OrderService;
import com.myimooc.guicedemo.server.PaymentService;
import com.myimooc.guicedemo.server.PriceService;

/**
 * @title ServerModule类
 * @describe 绑定依赖
 * @author zc
 * @version 1.0 2017-10-15
 */
public class ServerModule extends AbstractModule{

    @Override
    protected void configure() {
        bind(OrderService.class).to(OrderServiceImpl.class);
        bind(PaymentService.class).to(PaymentServiceImpl.class);
        bind(PriceService.class).to(PriceServiceImpl.class);
    }
    
    @Provides 
    @SessionId
    Long generateSessionId(){
        return System.currentTimeMillis();
    }
}

3.编写SessionId类

package com.myimooc.guicedemo.server.impl;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import com.google.inject.BindingAnnotation;

/**
 * @title SessionId注解
 * @describe 用来绑定数据
 * @author zc
 * @version 1.0 2017-10-15
 */
@Retention(RetentionPolicy.RUNTIME)
@BindingAnnotation
public @interface SessionId {

}

4.编写SessionManagerTest类

package com.myimooc.guicedemo.server.impl;

import static org.junit.Assert.assertNotEquals;

import javax.inject.Inject;

import org.junit.Before;
import org.junit.Test;

import com.google.inject.Guice;

/**
 * @title 测试类
 * @describe 测试@Provides
 * @author zc
 * @version 1.0 2017-10-15
 */
public class SessionManagerTest {
    
    @Inject
    SessionManager sessionManager;
    
    @Before
    public void setUp(){
        Guice.createInjector(new ServerModule())
             .injectMembers(this);
    }
    
    @Test
    public void testGetSessionId() throws InterruptedException{
        Long sessionId1 = sessionManager.getSessionId();
        Thread.sleep(1000);
        Long sessionId2 = sessionManager.getSessionId();
        assertNotEquals(sessionId1.longValue(), sessionId2.longValue());
    }
    
}
第四章:绑定依赖 4-1 绑定详解

绑定图解

绑定

类名绑定
实例绑定
连接绑定
Provider绑定
命名绑定
泛型绑定
集合绑定
4-2 模块组织

Module的相互关系

并列:Guice.createInjector(module1,module2,…)
嵌套:install(module)
覆盖:Modules.override(module1).with(module2)

Module何时被运行

Module里存放了很多表达式
Module不被“运行”
Guice.createInjector()时记录所有表达式

系统何时初始化

没有“初始化”概念,没有Spring的Configuration Time
injector.getInstance()时根据表达式调用构造函数
4-3 绑定示例

案例:HelloWorld与命令行

让HelloWorld打印命令行参数
让HelloWorld通过命令行决定启动哪个Applet

代码编写

1.编写MyApplet类

2.编写Applets类

3.编写StringWritingApplet类

4.编写PrintLineApplet类

5.编写MyDestination类

6.编写PrintStreamWriter类

7.编写Output类

8.编写Args类

9.编写HelloWorldModule类

10.编写PrintLineModule类

11.编写CommandLineModule类

12.编写MainModule类

13.编写App类

受篇幅限制,源码请到我的github地址查看

第五章:生命周期 5-1 基本介绍

生命周期或作用域

选择作用域

默认:适用于:一般实例,stateless,构造速度快
如:Parser、PriceCalulator
Singleton:适用于:stateful的实例,构造速度慢的实例,必须线程安全
如:数据库、网络连接
Session/Request:含有session/request信息的实例、stateful的实例
如:SessionSate
5-2 使用介绍

作用域的使用

作为类或者@Provides方法的属性
在绑定时使用In语句
@Singleton的线程安全性
第六章:切面编程 6-1 面向切面

Guice AOP

符合AOP Alliance的MethodInterceptor接口
MethodInterceptor可用于“Aspects”
    获取函数调用类、方法、参数
    控制是否执行函数调用

实现AOP

绑定MethodInterceptor
实现MethodInterceptor
在MethodInterceptor中注入Dependency

代码编写

1.编写Logged类

package com.myimooc.guicedemo.aop;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * @title Logged注解
 * @describe 用于标识需要记录日志的方法
 * @author zc
 * @version 1.0 2017-10-15
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface Logged {
    
}

2.编写LoggedInterceptor类

package com.myimooc.guicedemo.aop;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import com.google.common.base.Joiner;

/**
 * @title LoggedMethodInterceptor类
 * @describe 切面类,用于处理被拦截的方法,实现日志记录
 * @author zc
 * @version 1.0 2017-10-15
 */
public class LoggedInterceptor implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        
        // 获得调用参数
        invocation.getArguments();
        // 获得调用对象
        invocation.getClass();
        // 获得调用方法
        Method method = invocation.getMethod();
        
        // 记录日志
        System.out.println(String.format("Calling %s#%s(%s)",
            method.getDeclaringClass().getName(),
            method.getName(),
            Joiner.on(",").join(invocation.getArguments())));
        
        // 执行调用方法
        Object result = invocation.proceed();
        
        // 返回调用结果
        return result;
    }
}

3.编写LoggedModule类

package com.myimooc.guicedemo.aop;

import com.google.inject.AbstractModule;
import com.google.inject.matcher.Matchers;

/**
 * @title LoggedModule类
 * @describe 用于配置依赖绑定
 * @author zc
 * @version 1.0 2017-10-15
 */
public class LoggedModule extends AbstractModule{

    @Override
    protected void configure() {
        
        // 配置拦截任意类,带有@Logged注解修饰的方法
        bindInterceptor(
            Matchers.any(), 
            Matchers.annotatedWith(Logged.class), 
            new LoggedInterceptor());
        
    }
}
第七章:框架集成 7-1 协作框架

使用Guice与SpringBoot协作搭建Web应用

使用SpringBoot搭建简单的Web应用
使用Guice搭建业务逻辑

协作框架

7-2 案例实战

创建名为guicespring的maven工程

完成后的项目结构如下

受篇幅限制,源码请到我的github地址查看

协作小结

SpringBoot进行总控
各自绑定Guice Injector和Spring ApplicationContext
注意对象生命周期
第八章:课程总结 8-1 适用场景

Guice与Spring

Guice不是Spring的重制版
Spring绑定
    配置文件体现完整装配结构
    大量使用字符串:实例名:属性名
    在Config Time完成组装
Guice绑定
    Java代码描述绑定规则
    每个注入和绑定仅描述局部依赖
    没有Config Time

Guice的优点

代码量少
性能优异
支持泛型
Constructor绑定:Immutable objects,不再需要getter/setter
强类型
易于重构

Guice的缺点

Module和绑定规则不易理解
文档教程少,社区资源少
无法方便搭出特殊结构:如循环依赖
Guice仅仅是依赖注入框架,而Spring涵盖较多

从Spring迁移到Guice

不建议
Spring与Guice整合

新项目需要选择Dependency Injection方案

不妨尝试Guice
与其它组件或解决方案整合:注意对象生命周期
8-2 课程回顾

课程回顾

什么是Guce
Dependency Injection:改造Hello World程序
注入(Injection)
绑定(Binding)
作用域或生命周期(Scope)
Guice AOP
使用Guice与SpringBoot协作搭建Web应用

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67793.html

相关文章

  • 课网_《Spring入门篇》学习总结

    摘要:入门篇学习总结时间年月日星期三说明本文部分内容均来自慕课网。主要的功能是日志记录,性能统计,安全控制,事务处理,异常处理等等。 《Spring入门篇》学习总结 时间:2017年1月18日星期三说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:https://github.com/zccodere/s...个人学习源码:https://git...

    Ververica 评论0 收藏0
  • 课网_《SpringMVC拦截器》学习总结

    摘要:拦截器学习总结时间年月日星期六说明本文部分内容均来自慕课网。慕课网教学示例源码暂无。拦截器不依赖与容器,过滤器依赖与容器。拦截器只能对请求起作用,而过滤器则可以对几乎所有的请求起作用。共性问题在拦截器中处理,可以减少重复代码,便于维护。 《SpringMVC拦截器》学习总结 时间:2017年2月18日星期六说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.co...

    calx 评论0 收藏0
  • 课网_《Java实现Base64加密》学习总结

    摘要:时间年月日星期一说明本文部分内容均来自慕课网。多用于网络加密。散列函数函数或消息摘要函数主要作用散列函数用来验证数据的完整性。 时间:2017年4月10日星期一说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:https://github.com/zccodere/s...个人学习源码:https://github.com/zccodere...

    verano 评论0 收藏0
  • 课网_《模式的秘密之工厂模式》学习总结

    摘要:时间年月日星期日说明本文部分内容均来自慕课网。这对所有形态的工厂模式都是重要的这个系统的产品有至少一个的产品族同属于一个产品族的产品是设计成在一起使用的。 时间:2017年08月27日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:https://github.com/zccodere/s...学习源码:https://github.c...

    jsyzchen 评论0 收藏0
  • 课网_《JSON快速入门(Java版)》学习总结

    摘要:时间年月日星期日说明本文部分内容均来自慕课网。慕课网教学示例源码无个人学习源码第一章课程概述课程介绍课程须知本课程面向所有使用语言进行开发的小伙伴。 时间:2017年05月21日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:无个人学习源码:https://github.com/zccodere/s... 第一章:课程概述 1-1 ...

    shiina 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<