alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (DefaultMethodInterceptionTest.java)

This example Java source code file (DefaultMethodInterceptionTest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abstractmodule, annotation, atomicinteger, baseclass2, baz, bazimpl, foo, injector, interceptme, nonoverriding-foo, nonoverridingfoo, override, string, target, testcase

The DefaultMethodInterceptionTest.java Java example source code

/**
 * Copyright (C) 2014 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.inject.jdk8;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

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

import junit.framework.TestCase;

import org.aopalliance.intercept.MethodInterceptor;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Tests for interception of default methods.
 *
 * @author cgdecker@google.com (Colin Decker)
 */
public class DefaultMethodInterceptionTest extends TestCase {

  private static final AtomicInteger callCount = new AtomicInteger(0);
  private static final AtomicInteger interceptedCallCount = new AtomicInteger(0);

  // the interceptor's a lambda too
  private final MethodInterceptor interceptor = invocation -> {
    interceptedCallCount.incrementAndGet();
    return invocation.proceed();
  };

  @Override
  protected void setUp() throws Exception {
    callCount.set(0);
    interceptedCallCount.set(0);
  }

  @Retention(RUNTIME)
  @Target({METHOD, TYPE})
  public @interface InterceptMe {}

  /** Interface with a default method annotated to be intercepted. */
  public interface Foo {
    @InterceptMe
    default String defaultMethod() {
      callCount.incrementAndGet();
      return "Foo";
    }
  }

  /** Foo implementation that does not override the default method. */
  public static class NonOverridingFoo implements Foo {
    public String methodCallingDefault() {
      return "NonOverriding-" + defaultMethod();
    }
  }

  public void testInterceptedDefaultMethod() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
            interceptor);
        bind(Foo.class).to(NonOverridingFoo.class);
      }
    });

    Foo foo = injector.getInstance(Foo.class);
    assertEquals("Foo", foo.defaultMethod());
    assertEquals(1, callCount.get());
    assertEquals(1, interceptedCallCount.get());
  }

  public void testInterceptedDefaultMethod_calledByAnotherMethod() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
            interceptor);
      }
    });

    NonOverridingFoo foo = injector.getInstance(NonOverridingFoo.class);
    assertEquals("NonOverriding-Foo", foo.methodCallingDefault());
    assertEquals(1, callCount.get());
    assertEquals(1, interceptedCallCount.get());
  }

  /** A base class defining a method with the same signature as Foo's default method. */
  public static class BaseClass {
    // the definition of this method on the class will win over the default method
    public String defaultMethod() {
      callCount.incrementAndGet();
      return "BaseClass";
    }
  }

  /** Foo implementation that should use superclass method rather than default method. */
  public static class InheritingFoo extends BaseClass implements Foo {
  }

  public void testInterceptedDefaultMethod_whenParentClassDefinesNonInterceptedMethod() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
            interceptor);
        bind(Foo.class).to(InheritingFoo.class);
      }
    });

    // the concrete implementation that wins is not annotated
    Foo foo = injector.getInstance(Foo.class);
    assertEquals("BaseClass", foo.defaultMethod());
    assertEquals(1, callCount.get());
    assertEquals(0, interceptedCallCount.get());
  }

  /**
   * A base class defining an intercepted method with the same signature as Foo's default method.
   */
  public static class BaseClass2 {
    // the definition of this method on the class will win over the default method
    @InterceptMe
    public String defaultMethod() {
      callCount.incrementAndGet();
      return "BaseClass2";
    }
  }

  /**
   * Foo implementation that should use intercepted superclass method rather than default method.
   */
  public static class InheritingFoo2 extends BaseClass2 implements Foo {
  }

  public void testInterceptedDefaultMethod_whenParentClassDefinesInterceptedMethod() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
            interceptor);
        bind(Foo.class).to(InheritingFoo2.class);
      }
    });

    // the concrete implementation that wins is not annotated
    Foo foo = injector.getInstance(Foo.class);
    assertEquals("BaseClass2", foo.defaultMethod());
    assertEquals(1, callCount.get());
    assertEquals(1, interceptedCallCount.get());
  }

  public interface Baz {
    default String doSomething() {
      return "Baz";
    }

    String doSomethingElse();
  }

  public static class BazImpl implements Baz {

    @Override
    public String doSomethingElse() {
      return "BazImpl";
    }
  }

  public void testInterception_ofAllMethodsOnType() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindInterceptor(Matchers.subclassesOf(Baz.class), Matchers.any(), interceptor);
        bind(Baz.class).to(BazImpl.class);
      }
    });

    Baz baz = injector.getInstance(Baz.class);

    assertEquals("Baz", baz.doSomething());
    assertEquals("BazImpl", baz.doSomethingElse());

    assertEquals(2, interceptedCallCount.get());
  }

  public void testInterception_ofAllMethodsOnType_interceptsInheritedDefaultMethod() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindInterceptor(Matchers.subclassesOf(BazImpl.class), Matchers.any(), interceptor);
        bind(Baz.class).to(BazImpl.class);
      }
    });

    Baz baz = injector.getInstance(Baz.class);

    assertEquals("Baz", baz.doSomething());
    assertEquals("BazImpl", baz.doSomethingElse());

    assertEquals(2, interceptedCallCount.get());
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java DefaultMethodInterceptionTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.