Delete the interface NativeAspectFactory and make native aspects extend from NativeAspectClass.

This a large refactoring of the aspects, currently we have the following:
- AspectClasses: The interface AspectClass is a implemented by either
SkylarkAspectClass or NativeAspectClass<NativeAspectFactory>.
They are wrappers for the AspectFactories and they hold the information about
the Class<> of the factory.
- AspectFactories (FooAspect.java): Represented by the interfaces
ConfiguredAspectFactory and NativeAspectFactory, also by
the interface ConfiguredNativeAspectFactory which is the union of the two
aforementioned interfaces.
All aspects implement ConfiguredNativeAspectFactory except Skylark aspects
which implement only ConfiguredAspectFactory.

After this CL the distinction between NativeAspectFactories and NativeAspectClasses
dissappear, namely aspect that extends NativeAspectClass is considered native
and if it implements ConfiguredAspectFactory it is configured.
Therefore the interfaces NativeAspectFactory and ConfiguredNativeAspectFactory
both disappear.

With this refactoring the aspectFactoryMap in the ConfiguredRuleClassProvider
changes its type from (String -> Class<? extends NativeAspectClass>)
to (String -> NativeAspectClass) which means it is now able to have an instance
of the aspect instead of its Class only.
By doing this, it is now possible to pass parameters when creating an
aspect in the ConfiguredRuleClassProvider.

--
MOS_MIGRATED_REVID=120819647
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
index 1251fe1..c07d950 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
@@ -457,9 +457,8 @@
                   skylarkFunctionName));
         }
       } else {
-        final Class<? extends ConfiguredNativeAspectFactory> aspectFactoryClass =
-            ruleClassProvider.getAspectFactoryMap().get(aspect)
-                .asSubclass(ConfiguredNativeAspectFactory.class);
+        final NativeAspectClass aspectFactoryClass =
+            ruleClassProvider.getNativeAspectClassMap().get(aspect);
         if (aspectFactoryClass != null) {
           for (ConfiguredTargetKey targetSpec : targetSpecs) {
             aspectKeys.add(
@@ -469,7 +468,7 @@
                     // aspect and the base target while the top-level configuration is untrimmed.
                     targetSpec.getConfiguration(),
                     targetSpec.getConfiguration(),
-                    new NativeAspectClass<ConfiguredNativeAspectFactory>(aspectFactoryClass)));
+                    aspectFactoryClass));
           }
         } else {
           throw new ViewCreationFailedException("Aspect '" + aspect + "' is unknown");
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredNativeAspectFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredNativeAspectFactory.java
deleted file mode 100644
index e315141..0000000
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredNativeAspectFactory.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 The Bazel Authors. All rights reserved.
-//
-// 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.devtools.build.lib.analysis;
-
-import com.google.devtools.build.lib.packages.NativeAspectClass;
-
-/**
- * A union of {@link ConfiguredAspectFactory} and
- * {@link com.google.devtools.build.lib.packages.NativeAspectClass.NativeAspectFactory}
- * All native aspect classes should implement this interface.
- *
- */
-public interface ConfiguredNativeAspectFactory
-    extends ConfiguredAspectFactory, NativeAspectClass.NativeAspectFactory {
-
-}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
index e4a4a2c..bfc8b5b 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
@@ -36,7 +36,7 @@
 import com.google.devtools.build.lib.graph.Digraph;
 import com.google.devtools.build.lib.graph.Node;
 import com.google.devtools.build.lib.packages.Attribute;
-import com.google.devtools.build.lib.packages.NativeAspectClass.NativeAspectFactory;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.packages.RuleClass;
 import com.google.devtools.build.lib.packages.RuleClassProvider;
 import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
@@ -93,7 +93,7 @@
 
     private final Map<String, RuleClass> ruleClassMap = new HashMap<>();
     private final Map<String, RuleDefinition> ruleDefinitionMap = new HashMap<>();
-    private final Map<String, Class<? extends NativeAspectFactory>> aspectFactoryMap =
+    private final Map<String, NativeAspectClass> nativeAspectClassMap =
         new HashMap<>();
     private final Map<Class<? extends RuleDefinition>, RuleClass> ruleMap = new HashMap<>();
     private final Digraph<Class<? extends RuleDefinition>> dependencyGraph =
@@ -161,10 +161,8 @@
       return this;
     }
 
-    public Builder addAspectFactory(
-        String name, Class<? extends ConfiguredNativeAspectFactory> configuredAspectFactoryClass) {
-      aspectFactoryMap.put(name, configuredAspectFactoryClass);
-
+    public Builder addNativeAspectClass(NativeAspectClass aspectFactoryClass) {
+      nativeAspectClassMap.put(aspectFactoryClass.getName(), aspectFactoryClass);
       return this;
     }
 
@@ -264,7 +262,7 @@
           toolsRepository,
           ImmutableMap.copyOf(ruleClassMap),
           ImmutableMap.copyOf(ruleDefinitionMap),
-          ImmutableMap.copyOf(aspectFactoryMap),
+          ImmutableMap.copyOf(nativeAspectClassMap),
           defaultWorkspaceFilePrefix.toString(),
           defaultWorkspaceFileSuffix.toString(),
           ImmutableList.copyOf(buildInfoFactories),
@@ -344,7 +342,7 @@
   /**
    * Maps aspect name to the aspect factory meta class.
    */
-  private final ImmutableMap<String, Class<? extends NativeAspectFactory>> aspectFactoryMap;
+  private final ImmutableMap<String, NativeAspectClass> nativeAspectClassMap;
 
   /**
    * The configuration options that affect the behavior of the rules.
@@ -381,7 +379,7 @@
       String toolsRepository,
       ImmutableMap<String, RuleClass> ruleClassMap,
       ImmutableMap<String, RuleDefinition> ruleDefinitionMap,
-      ImmutableMap<String, Class<? extends NativeAspectFactory>> aspectFactoryMap,
+      ImmutableMap<String, NativeAspectClass> nativeAspectClassMap,
       String defaultWorkspaceFilePrefix,
       String defaultWorkspaceFileSuffix,
       ImmutableList<BuildInfoFactory> buildInfoFactories,
@@ -398,7 +396,7 @@
     this.toolsRepository = toolsRepository;
     this.ruleClassMap = ruleClassMap;
     this.ruleDefinitionMap = ruleDefinitionMap;
-    this.aspectFactoryMap = aspectFactoryMap;
+    this.nativeAspectClassMap = nativeAspectClassMap;
     this.defaultWorkspaceFilePrefix = defaultWorkspaceFilePrefix;
     this.defaultWorkspaceFileSuffix = defaultWorkspaceFileSuffix;
     this.buildInfoFactories = buildInfoFactories;
@@ -436,8 +434,13 @@
   }
 
   @Override
-  public Map<String, Class<? extends NativeAspectFactory>> getAspectFactoryMap() {
-    return aspectFactoryMap;
+  public Map<String, NativeAspectClass> getNativeAspectClassMap() {
+    return nativeAspectClassMap;
+  }
+
+  @Override
+  public NativeAspectClass getNativeAspectClass(String key) {
+    return nativeAspectClassMap.get(key);
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
index ef48488..cf66d51 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
@@ -484,9 +484,9 @@
           aspect.getDefinition().getAttributeAspects().get(attribute.getName())) {
         if (aspectClass.equals(aspect.getAspectClass())) {
           aspectCandidates.add(aspect);
-        } else if (aspectClass instanceof NativeAspectClass<?>) {
+        } else if (aspectClass instanceof NativeAspectClass) {
           aspectCandidates.add(
-              Aspect.forNative((NativeAspectClass<?>) aspectClass, aspect.getParameters()));
+              Aspect.forNative((NativeAspectClass) aspectClass, aspect.getParameters()));
         } else {
           // If we ever want to support this specifying arbitrary aspects for Skylark aspects,
           // we will need to do a Skyframe call here to load an up-to-date definition.
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index 61d5224..3f7896b 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -76,8 +76,11 @@
 import com.google.devtools.build.lib.rules.android.AndroidBinaryOnlyRule;
 import com.google.devtools.build.lib.rules.android.AndroidConfiguration;
 import com.google.devtools.build.lib.rules.android.AndroidLibraryBaseRule;
+import com.google.devtools.build.lib.rules.android.AndroidNeverlinkAspect;
 import com.google.devtools.build.lib.rules.android.AndroidRuleClasses;
 import com.google.devtools.build.lib.rules.android.AndroidSkylarkCommon;
+import com.google.devtools.build.lib.rules.android.DexArchiveAspect;
+import com.google.devtools.build.lib.rules.android.JackAspect;
 import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions;
 import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
 import com.google.devtools.build.lib.rules.apple.AppleToolchain;
@@ -101,6 +104,7 @@
 import com.google.devtools.build.lib.rules.objc.AppleSkylarkCommon;
 import com.google.devtools.build.lib.rules.objc.AppleWatch1ExtensionRule;
 import com.google.devtools.build.lib.rules.objc.AppleWatchExtensionBinaryRule;
+import com.google.devtools.build.lib.rules.objc.BazelJ2ObjcProtoAspect;
 import com.google.devtools.build.lib.rules.objc.ExperimentalObjcLibraryRule;
 import com.google.devtools.build.lib.rules.objc.IosApplicationRule;
 import com.google.devtools.build.lib.rules.objc.IosDeviceRule;
@@ -109,6 +113,7 @@
 import com.google.devtools.build.lib.rules.objc.IosFrameworkBinaryRule;
 import com.google.devtools.build.lib.rules.objc.IosFrameworkRule;
 import com.google.devtools.build.lib.rules.objc.IosTestRule;
+import com.google.devtools.build.lib.rules.objc.J2ObjcAspect;
 import com.google.devtools.build.lib.rules.objc.J2ObjcCommandLineOptions;
 import com.google.devtools.build.lib.rules.objc.J2ObjcConfiguration;
 import com.google.devtools.build.lib.rules.objc.J2ObjcLibraryBaseRule;
@@ -139,6 +144,8 @@
  * A rule class provider implementing the rules Bazel knows.
  */
 public class BazelRuleClassProvider {
+  public static final String TOOLS_REPOSITORY = "@bazel_tools";
+
   /**
    * Used by the build encyclopedia generator.
    */
@@ -236,7 +243,7 @@
       ImmutableMap.of(
           "android_common", new AndroidSkylarkCommon(),
           "apple_common", new AppleSkylarkCommon());
-          
+
   public static void setup(ConfiguredRuleClassProvider.Builder builder) {
     builder
         .addBuildInfoFactory(new BazelJavaBuildInfoFactory())
@@ -245,7 +252,7 @@
         .setConfigurationCollectionFactory(new BazelConfigurationCollection())
         .setPrelude("//tools/build_rules:prelude_bazel")
         .setRunfilesPrefix("")
-        .setToolsRepository("@bazel_tools")
+        .setToolsRepository(TOOLS_REPOSITORY)
         .setPrerequisiteValidator(new BazelPrerequisiteValidator())
         .setSkylarkAccessibleTopLevels(skylarkBuiltinJavaObects);
 
@@ -255,6 +262,20 @@
       builder.addConfigurationOptions(fragmentOptions);
     }
 
+    AndroidNeverlinkAspect androidNeverlinkAspect = new AndroidNeverlinkAspect();
+    DexArchiveAspect dexArchiveAspect = new DexArchiveAspect(TOOLS_REPOSITORY);
+    JackAspect jackAspect = new JackAspect();
+    BazelJ2ObjcProtoAspect bazelJ2ObjcProtoAspect = new BazelJ2ObjcProtoAspect(TOOLS_REPOSITORY);
+    J2ObjcAspect j2ObjcAspect = new J2ObjcAspect(TOOLS_REPOSITORY, bazelJ2ObjcProtoAspect);
+    AndroidStudioInfoAspect androidStudioInfoAspect = new AndroidStudioInfoAspect(TOOLS_REPOSITORY);
+
+    builder.addNativeAspectClass(androidNeverlinkAspect);
+    builder.addNativeAspectClass(dexArchiveAspect);
+    builder.addNativeAspectClass(jackAspect);
+    builder.addNativeAspectClass(bazelJ2ObjcProtoAspect);
+    builder.addNativeAspectClass(j2ObjcAspect);
+    builder.addNativeAspectClass(androidStudioInfoAspect);
+
     builder.addRuleDefinition(new WorkspaceBaseRule());
 
     builder.addRuleDefinition(new BaseRuleClasses.BaseRule());
@@ -331,9 +352,10 @@
     builder.addRuleDefinition(new AndroidRuleClasses.AndroidBaseRule());
     builder.addRuleDefinition(new AndroidRuleClasses.AndroidAaptBaseRule());
     builder.addRuleDefinition(new AndroidRuleClasses.AndroidResourceSupportRule());
-    builder.addRuleDefinition(new AndroidRuleClasses.AndroidBinaryBaseRule());
+    builder.addRuleDefinition(new AndroidRuleClasses.AndroidBinaryBaseRule(
+        androidNeverlinkAspect, dexArchiveAspect, jackAspect));
     builder.addRuleDefinition(new AndroidBinaryOnlyRule());
-    builder.addRuleDefinition(new AndroidLibraryBaseRule());
+    builder.addRuleDefinition(new AndroidLibraryBaseRule(androidNeverlinkAspect, jackAspect));
     builder.addRuleDefinition(new BazelAndroidLibraryRule());
     builder.addRuleDefinition(new BazelAndroidBinaryRule());
 
@@ -377,7 +399,7 @@
     builder.addRuleDefinition(new XcodeVersionRule());
     builder.addRuleDefinition(new XcodeConfigRule());
     builder.addRuleDefinition(new J2ObjcLibraryBaseRule());
-    builder.addRuleDefinition(new BazelJ2ObjcLibraryRule());
+    builder.addRuleDefinition(new BazelJ2ObjcLibraryRule(j2ObjcAspect));
 
     builder.addRuleDefinition(new BazelExtraActionRule());
     builder.addRuleDefinition(new BazelActionListenerRule());
@@ -396,8 +418,6 @@
     builder.addRuleDefinition(new AndroidSdkRepositoryRule());
     builder.addRuleDefinition(new AndroidNdkRepositoryRule());
 
-    builder.addAspectFactory(AndroidStudioInfoAspect.NAME, AndroidStudioInfoAspect.class);
-
     builder.addConfigurationFragment(new BazelConfiguration.Loader());
     builder.addConfigurationFragment(new CppConfigurationLoader(
         Functions.<String>identity()));
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/objc/BazelJ2ObjcLibraryRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/objc/BazelJ2ObjcLibraryRule.java
index 4c71e4b..551a424 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/objc/BazelJ2ObjcLibraryRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/objc/BazelJ2ObjcLibraryRule.java
@@ -32,6 +32,11 @@
  * Concrete implementation of J2ObjCLibraryBaseRule.
  */
 public class BazelJ2ObjcLibraryRule implements RuleDefinition {
+  private final J2ObjcAspect j2ObjcAspect;
+
+  public BazelJ2ObjcLibraryRule(J2ObjcAspect j2ObjcAspect) {
+    this.j2ObjcAspect = j2ObjcAspect;
+  }
 
   @Override
   public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
@@ -62,7 +67,7 @@
           </p>
           <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
         .add(attr("deps", LABEL_LIST)
-            .aspect(J2ObjcAspect.class)
+            .aspect(j2ObjcAspect)
             .direct_compile_time_input()
             .allowedRuleClasses("j2objc_library", "java_library", "java_import")
             .allowedFileTypes())
diff --git a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java
index fa83b28..39dfff6 100644
--- a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java
@@ -26,7 +26,6 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.io.ByteSource;
-import com.google.devtools.build.lib.Constants;
 import com.google.devtools.build.lib.actions.Action;
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.Artifact;
@@ -35,7 +34,7 @@
 import com.google.devtools.build.lib.analysis.AnalysisUtils;
 import com.google.devtools.build.lib.analysis.ConfiguredAspect;
 import com.google.devtools.build.lib.analysis.ConfiguredAspect.Builder;
-import com.google.devtools.build.lib.analysis.ConfiguredNativeAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
 import com.google.devtools.build.lib.analysis.RuleContext;
@@ -59,6 +58,7 @@
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.rules.android.AndroidIdeInfoProvider;
@@ -86,7 +86,7 @@
 /**
  * Generates ide-build information for Android Studio.
  */
-public class AndroidStudioInfoAspect implements ConfiguredNativeAspectFactory {
+public class AndroidStudioInfoAspect extends NativeAspectClass implements ConfiguredAspectFactory {
   public static final String NAME = "AndroidStudioInfoAspect";
 
   // Output groups.
@@ -94,6 +94,11 @@
   public static final String IDE_INFO = "ide-info";
   public static final String IDE_INFO_TEXT = "ide-info-text";
   public static final String IDE_RESOLVE = "ide-resolve";
+  private final String toolsRepository;
+
+  public AndroidStudioInfoAspect(String toolsRepository) {
+    this.toolsRepository = toolsRepository;
+  }
 
   private static class PrerequisiteAttr {
     public final String name;
@@ -129,14 +134,14 @@
   @Override
   public AspectDefinition getDefinition(AspectParameters aspectParameters) {
     AspectDefinition.Builder builder = new AspectDefinition.Builder(NAME)
-        .attributeAspect("runtime_deps", AndroidStudioInfoAspect.class)
-        .attributeAspect("resources", AndroidStudioInfoAspect.class)
+        .attributeAspect("runtime_deps", this)
+        .attributeAspect("resources", this)
         .add(attr("$packageParser", LABEL).cfg(HOST).exec()
             .value(Label.parseAbsoluteUnchecked(
-                Constants.TOOLS_REPOSITORY + "//tools/android:PackageParser")));
+                toolsRepository + "//tools/android:PackageParser")));
 
     for (PrerequisiteAttr prerequisiteAttr : PREREQUISITE_ATTRS) {
-      builder.attributeAspect(prerequisiteAttr.name, AndroidStudioInfoAspect.class);
+      builder.attributeAspect(prerequisiteAttr.name, this);
     }
 
     return builder.build();
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Aspect.java b/src/main/java/com/google/devtools/build/lib/packages/Aspect.java
index cff38f9..dfd7e5c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Aspect.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Aspect.java
@@ -43,11 +43,11 @@
   }
 
   public static Aspect forNative(
-      NativeAspectClass<?> nativeAspectClass, AspectParameters parameters) {
+      NativeAspectClass nativeAspectClass, AspectParameters parameters) {
     return new Aspect(nativeAspectClass, nativeAspectClass.getDefinition(parameters), parameters);
   }
 
-  public static Aspect forNative(NativeAspectClass<?> nativeAspectClass) {
+  public static Aspect forNative(NativeAspectClass nativeAspectClass) {
     return forNative(nativeAspectClass, AspectParameters.EMPTY);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
index be1bd0b..c9b8a3b 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
@@ -23,7 +23,6 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
-import com.google.devtools.build.lib.packages.NativeAspectClass.NativeAspectFactory;
 import com.google.devtools.build.lib.util.Preconditions;
 
 import java.util.Collection;
@@ -249,13 +248,10 @@
      * but we cannot reference that interface here.
      */
     @SafeVarargs
-    public final Builder attributeAspect(
-        String attribute, Class<? extends NativeAspectFactory>... aspectFactories) {
+    public final Builder attributeAspect(String attribute, NativeAspectClass... aspectClasses) {
       Preconditions.checkNotNull(attribute);
-      for (Class<? extends NativeAspectFactory> aspectFactory : aspectFactories) {
-        this
-            .attributeAspect(
-                attribute, new NativeAspectClass<>(Preconditions.checkNotNull(aspectFactory)));
+      for (NativeAspectClass aspectClass : aspectClasses) {
+        this.attributeAspect(attribute, Preconditions.checkNotNull(aspectClass));
       }
       return this;
     }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index aeac774..4b9f7fe 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -23,7 +23,6 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.cmdline.Label;
-import com.google.devtools.build.lib.packages.NativeAspectClass.NativeAspectFactory;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.syntax.ClassObject;
 import com.google.devtools.build.lib.syntax.ClassObject.SkylarkClassObject;
@@ -73,8 +72,8 @@
     public abstract Aspect getAspect(Rule rule);
   }
 
-  private static class NativeRuleAspect extends RuleAspect<NativeAspectClass<?>> {
-    public NativeRuleAspect(NativeAspectClass<?> aspectClass,
+  private static class NativeRuleAspect extends RuleAspect<NativeAspectClass> {
+    public NativeRuleAspect(NativeAspectClass aspectClass,
         Function<Rule, AspectParameters> parametersExtractor) {
       super(aspectClass, parametersExtractor);
     }
@@ -151,7 +150,7 @@
     // TODO(bazel-team): Move this elsewhere.
     DATA,
 
-    /** 
+    /**
      * Transition to one or more configurations. To obtain the actual child configurations,
      * invoke {@link Attribute#getSplitTransition(Rule)}. See {@link SplitTransition}.
      **/
@@ -297,7 +296,7 @@
      */
     SplitTransition<?> apply(Rule fromRule);
   }
-  
+
   /**
    * Implementation of {@link SplitTransitionProvider} that returns a single {@link SplitTransition}
    * regardless of the originating rule.
@@ -827,32 +826,13 @@
     }
 
     /**
-     * Asserts that a particular aspect probably needs to be computed for all direct dependencies
-     * through this attribute.
-     */
-    public <T extends NativeAspectFactory> Builder<TYPE> aspect(Class<T> aspect) {
-      return this.aspect(aspect, NO_PARAMETERS);
-    }
-
-    /**
-     * Asserts that a particular parameterized aspect probably needs to be computed for all direct
-     * dependencies through this attribute.
-     *
-     * @param evaluator function that extracts aspect parameters from rule.
-     */
-    public <T extends NativeAspectFactory> Builder<TYPE> aspect(
-        Class<T> aspect, Function<Rule, AspectParameters> evaluator) {
-      return this.aspect(new NativeAspectClass<T>(aspect), evaluator);
-    }
-
-    /**
      * Asserts that a particular parameterized aspect probably needs to be computed for all direct
      * dependencies through this attribute.
      *
      * @param evaluator function that extracts aspect parameters from rule.
      */
     public Builder<TYPE> aspect(
-        NativeAspectClass<?> aspect, Function<Rule, AspectParameters> evaluator) {
+        NativeAspectClass aspect, Function<Rule, AspectParameters> evaluator) {
       this.aspects.add(new NativeRuleAspect(aspect, evaluator));
       return this;
     }
@@ -861,7 +841,7 @@
      * Asserts that a particular parameterized aspect probably needs to be computed for all direct
      * dependencies through this attribute.
      */
-    public Builder<TYPE> aspect(NativeAspectClass<?> aspect) {
+    public Builder<TYPE> aspect(NativeAspectClass aspect) {
       Function<Rule, AspectParameters> noParameters =
           new Function<Rule, AspectParameters>() {
             @Override
@@ -1407,10 +1387,10 @@
   }
 
   /**
-   * Returns the split configuration transition for this attribute. 
-   * 
+   * Returns the split configuration transition for this attribute.
+   *
    * @param rule the originating {@link Rule} which owns this attribute
-   * @throws IllegalStateException if {@link #hasSplitConfigurationTransition} is not true 
+   * @throws IllegalStateException if {@link #hasSplitConfigurationTransition} is not true
    */
   public SplitTransition<?> getSplitTransition(Rule rule) {
     Preconditions.checkState(hasSplitConfigurationTransition());
diff --git a/src/main/java/com/google/devtools/build/lib/packages/NativeAspectClass.java b/src/main/java/com/google/devtools/build/lib/packages/NativeAspectClass.java
index febf653..905862a 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/NativeAspectClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/NativeAspectClass.java
@@ -20,51 +20,13 @@
  * <p>This class just wraps a {@link java.lang.Class} implementing the
  * aspect factory. All wrappers of the same class are equal.
  */
-public final class NativeAspectClass<T extends NativeAspectClass.NativeAspectFactory>
-    implements AspectClass {
-  private final Class<? extends T> nativeClass;
-
-  public NativeAspectClass(Class<? extends T> nativeClass) {
-    this.nativeClass = nativeClass;
-  }
+public abstract class NativeAspectClass implements AspectClass {
 
   @Override
   public String getName() {
-    return nativeClass.getSimpleName();
+    return getClass().getSimpleName();
   }
 
-  public AspectDefinition getDefinition(AspectParameters aspectParameters) {
-    return newInstance().getDefinition(aspectParameters);
-  }
+  public abstract AspectDefinition getDefinition(AspectParameters aspectParameters);
 
-  public T newInstance() {
-    try {
-      return nativeClass.newInstance();
-    } catch (Exception e) {
-      throw new IllegalStateException(e);
-    }
-  }
-
-  @Override
-  public int hashCode() {
-    return nativeClass.hashCode();
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (!(obj instanceof NativeAspectClass)) {
-      return false;
-    }
-    return nativeClass.equals(((NativeAspectClass<?>) obj).nativeClass);
-  }
-
-  /**
-   * Every native aspect should implement this interface.
-   */
-  public interface NativeAspectFactory {
-    /**
-     * Returns the definition of the aspect.
-     */
-    AspectDefinition getDefinition(AspectParameters aspectParameters);
-  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
index 7a3566a..f5cf092 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
@@ -16,7 +16,6 @@
 
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.events.EventHandler;
-import com.google.devtools.build.lib.packages.NativeAspectClass.NativeAspectFactory;
 import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.Environment.Extension;
 import com.google.devtools.build.lib.syntax.Mutability;
@@ -66,7 +65,7 @@
   /**
    * Returns a map from aspect names to aspect factory objects.
    */
-  Map<String, Class<? extends NativeAspectFactory>> getAspectFactoryMap();
+  Map<String, NativeAspectClass> getNativeAspectClassMap();
 
   /**
    * Returns the default content that should be added at the beginning of the WORKSPACE file.
@@ -88,4 +87,9 @@
    * Returns the path to the tools repository
    */
   String getToolsRepository();
+
+  /**
+   * Retrieves an aspect from the aspect factory map using the key provided
+   */
+  NativeAspectClass getNativeAspectClass(String key);
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java
index 6c295be..13686f8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java
@@ -35,6 +35,15 @@
  * Rule definition for the android_library rule.
  */
 public final class AndroidLibraryBaseRule implements RuleDefinition {
+  private final AndroidNeverlinkAspect androidNeverlinkAspect;
+  private final JackAspect jackAspect;
+
+  public AndroidLibraryBaseRule(AndroidNeverlinkAspect androidNeverlinkAspect,
+      JackAspect jackAspect) {
+    this.androidNeverlinkAspect = androidNeverlinkAspect;
+    this.jackAspect = jackAspect;
+  }
+
   @Override
   public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironment env) {
     return builder
@@ -73,8 +82,8 @@
         .override(builder.copy("deps")
             .allowedRuleClasses(AndroidRuleClasses.ALLOWED_DEPENDENCIES)
             .allowedFileTypes()
-            .aspect(JackAspect.class)
-            .aspect(AndroidNeverlinkAspect.class))
+            .aspect(jackAspect)
+            .aspect(androidNeverlinkAspect))
         /* <!-- #BLAZE_RULE(android_library).ATTRIBUTE(exports) -->
         The closure of all rules reached via <code>exports</code> attributes
         are considered direct dependencies of any rule that directly depends on the
@@ -84,8 +93,8 @@
         .add(attr("exports", LABEL_LIST)
             .allowedRuleClasses(AndroidRuleClasses.ALLOWED_DEPENDENCIES)
             .allowedFileTypes(/*May not have files in exports!*/)
-            .aspect(JackAspect.class)
-            .aspect(AndroidNeverlinkAspect.class))
+            .aspect(jackAspect)
+            .aspect(androidNeverlinkAspect))
         .add(attr("alwayslink", BOOLEAN).undocumented("purely informational for now"))
         /* <!-- #BLAZE_RULE(android_library).ATTRIBUTE(neverlink) -->
         Only use this library for compilation and not at runtime.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
index b0a3e0d..db87300 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
@@ -15,7 +15,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.analysis.ConfiguredAspect;
-import com.google.devtools.build.lib.analysis.ConfiguredNativeAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
 import com.google.devtools.build.lib.analysis.RuleContext;
@@ -23,6 +23,7 @@
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.rules.java.JavaCommon;
 import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
 import com.google.devtools.build.lib.rules.java.JavaRuntimeJarProvider;
@@ -38,7 +39,7 @@
  * <p>One would think that using the compile time classpath would be enough, but alas, those are
  * ijars,
  */
-public class AndroidNeverlinkAspect implements ConfiguredNativeAspectFactory {
+public class AndroidNeverlinkAspect extends NativeAspectClass implements ConfiguredAspectFactory {
   public static final String NAME = "AndroidNeverlinkAspect";
   private static final ImmutableList<String> ATTRIBUTES =
       ImmutableList.of(
@@ -80,7 +81,7 @@
   public AspectDefinition getDefinition(AspectParameters aspectParameters) {
     AspectDefinition.Builder builder = new AspectDefinition.Builder("AndroidNeverlinkAspect");
     for (String attribute : ATTRIBUTES) {
-      builder.attributeAspect(attribute, AndroidNeverlinkAspect.class);
+      builder.attributeAspect(attribute, this);
     }
 
     return builder
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
index 0cb5c90..b48e8b5 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
@@ -543,6 +543,19 @@
    * Base class for Android rule definitions that produce binaries.
    */
   public static final class AndroidBinaryBaseRule implements RuleDefinition {
+
+    private final AndroidNeverlinkAspect androidNeverlinkAspect;
+    private final DexArchiveAspect dexArchiveAspect;
+    private final JackAspect jackAspect;
+
+    public AndroidBinaryBaseRule(AndroidNeverlinkAspect androidNeverlinkAspect,
+        DexArchiveAspect dexArchiveAspect,
+        JackAspect jackAspect) {
+      this.androidNeverlinkAspect = androidNeverlinkAspect;
+      this.dexArchiveAspect = dexArchiveAspect;
+      this.jackAspect = jackAspect;
+    }
+
     @Override
     public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironment env) {
       return builder
@@ -575,9 +588,9 @@
               .cfg(ANDROID_SPLIT_TRANSITION)
               .allowedRuleClasses(ALLOWED_DEPENDENCIES)
               .allowedFileTypes()
-              .aspect(AndroidNeverlinkAspect.class)
-              .aspect(DexArchiveAspect.class)
-              .aspect(JackAspect.class))
+              .aspect(androidNeverlinkAspect)
+              .aspect(dexArchiveAspect)
+              .aspect(jackAspect))
           // Proguard rule specifying master list of classes to keep during legacy multidexing.
           .add(attr("$build_incremental_dexmanifest", LABEL).cfg(HOST).exec()
               .value(env.getToolsLabel(BUILD_INCREMENTAL_DEXMANIFEST_LABEL)))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java
index 09698cd..06698e1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java
@@ -14,7 +14,6 @@
 package com.google.devtools.build.lib.rules.android;
 
 import static com.google.common.base.Preconditions.checkState;
-import static com.google.devtools.build.lib.Constants.TOOLS_REPOSITORY;
 import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
 import static com.google.devtools.build.lib.packages.Attribute.attr;
 import static com.google.devtools.build.lib.packages.BuildType.LABEL;
@@ -35,7 +34,7 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
-import com.google.devtools.build.lib.packages.NativeAspectClass.NativeAspectFactory;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.rules.java.JavaCommon;
 import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
 import com.google.devtools.build.lib.rules.java.JavaRuntimeJarProvider;
@@ -43,11 +42,16 @@
 /**
  * Aspect to {@link DexArchiveProvider build .dex Archives} from Jars.
  */
-public final class DexArchiveAspect implements NativeAspectFactory, ConfiguredAspectFactory {
-  private static final String NAME = "DexArchiveAspect";
+public final class DexArchiveAspect extends NativeAspectClass implements ConfiguredAspectFactory {
+  public static final String NAME = "DexArchiveAspect";
   private static final String ASPECT_DEXBUILDER_PREREQ = "$dex_archive_dexbuilder";
   private static final ImmutableList<String> TRANSITIVE_ATTRIBUTES =
       ImmutableList.of("deps", "exports", "runtime_deps");
+  private final String toolsRepository;
+
+  public DexArchiveAspect(String toolsRepository) {
+    this.toolsRepository = toolsRepository;
+  }
 
   @Override
   public AspectDefinition getDefinition(AspectParameters params) {
@@ -56,10 +60,10 @@
         .requireProvider(JavaCompilationArgsProvider.class)
         .add(attr(ASPECT_DEXBUILDER_PREREQ, LABEL).cfg(HOST).exec()
         // Parse label here since we don't have RuleDefinitionEnvironment.getLabel like in a rule
-            .value(Label.parseAbsoluteUnchecked(TOOLS_REPOSITORY + "//tools/android:dexbuilder")))
+            .value(Label.parseAbsoluteUnchecked(toolsRepository + "//tools/android:dexbuilder")))
         .requiresConfigurationFragments(AndroidConfiguration.class);
     for (String attr : TRANSITIVE_ATTRIBUTES) {
-      result.attributeAspect(attr, DexArchiveAspect.class);
+      result.attributeAspect(attr, this);
     }
     return result.build();
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/JackAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/JackAspect.java
index cceff8a..7d15c27 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/JackAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/JackAspect.java
@@ -31,7 +31,7 @@
 import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
-import com.google.devtools.build.lib.packages.NativeAspectClass.NativeAspectFactory;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidSdkLabel;
 import com.google.devtools.build.lib.rules.java.JavaCommon;
 import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
@@ -39,7 +39,7 @@
 import java.util.List;
 
 /** Aspect to provide Jack support to rules which have java sources. */
-public final class JackAspect implements NativeAspectFactory, ConfiguredAspectFactory {
+public final class JackAspect extends NativeAspectClass implements ConfiguredAspectFactory {
   public static final String NAME = "JackAspect";
 
   @Override
@@ -56,9 +56,9 @@
         .add(attr(":android_sdk", LABEL)
               .allowedRuleClasses("android_sdk")
               .value(new AndroidSdkLabel(androidSdk)))
-        .attributeAspect("deps", JackAspect.class)
-        .attributeAspect("exports", JackAspect.class)
-        .attributeAspect("runtime_deps", JackAspect.class)
+        .attributeAspect("deps", this)
+        .attributeAspect("exports", this)
+        .attributeAspect("runtime_deps", this)
         .requiresConfigurationFragments(AndroidConfiguration.class)
         .build();
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java
index c01fbda..f89ac4b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java
@@ -20,10 +20,9 @@
 import static com.google.devtools.build.lib.rules.objc.J2ObjcSource.SourceType;
 
 import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.Constants;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.ConfiguredAspect;
-import com.google.devtools.build.lib.analysis.ConfiguredNativeAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
 import com.google.devtools.build.lib.analysis.RuleContext;
@@ -32,6 +31,7 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
 import com.google.devtools.build.lib.rules.apple.AppleToolchain;
 import com.google.devtools.build.lib.rules.proto.ProtoCommon;
@@ -55,12 +55,19 @@
  * by this class and provided by proto_library will be exported all the way to objc_binary for ObjC
  * compilation and linking into the final application bundle.
  */
-public abstract class AbstractJ2ObjcProtoAspect implements ConfiguredNativeAspectFactory {
-  public static final String NAME = "J2ObjcProtoAspect";
+public abstract class AbstractJ2ObjcProtoAspect extends NativeAspectClass
+  implements ConfiguredAspectFactory {
+
   private static final Iterable<Attribute> DEPENDENT_ATTRIBUTES = ImmutableList.of(
       new Attribute("$protobuf_lib", Mode.TARGET),
       new Attribute("deps", Mode.TARGET));
 
+  protected final String toolsRepository;
+
+  public AbstractJ2ObjcProtoAspect(String toolsRepository) {
+    this.toolsRepository = toolsRepository;
+  }
+
   @Override
   public AspectDefinition getDefinition(AspectParameters aspectParameters) {
     AspectDefinition.Builder builder = new AspectDefinition.Builder("J2ObjcProtoAspect")
@@ -70,14 +77,14 @@
             J2ObjcConfiguration.class,
             ObjcConfiguration.class,
             ProtoConfiguration.class)
-        .attributeAspect("deps", getClass())
-        .attributeAspect("exports", getClass())
-        .attributeAspect("runtime_deps", getClass())
+        .attributeAspect("deps", this)
+        .attributeAspect("exports", this)
+        .attributeAspect("runtime_deps", this)
         .add(attr("$protobuf_lib", LABEL)
             .value(Label.parseAbsoluteUnchecked("//third_party/java/j2objc:proto_runtime")))
         .add(attr("$xcrunwrapper", LABEL).cfg(HOST).exec()
             .value(Label.parseAbsoluteUnchecked(
-                Constants.TOOLS_REPOSITORY + "//tools/objc:xcrunwrapper")))
+                toolsRepository + "//tools/objc:xcrunwrapper")))
         .add(attr(":xcode_config", LABEL)
             .allowedRuleClasses("xcode_config")
             .checkConstraints()
@@ -97,7 +104,7 @@
       ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters)
       throws InterruptedException {
     if (!checkShouldCreateAspect(ruleContext)) {
-      return new ConfiguredAspect.Builder(NAME, ruleContext).build();
+      return new ConfiguredAspect.Builder(getName(), ruleContext).build();
     }
 
     ProtoSourcesProvider protoSourcesProvider = base.getProvider(ProtoSourcesProvider.class);
@@ -154,7 +161,7 @@
     NestedSet<Artifact> j2ObjcTransitiveClassMappingFiles = j2ObjcTransitiveClassMappingFiles(
         ruleContext, classMappingFiles);
 
-    return new ConfiguredAspect.Builder(NAME, ruleContext)
+    return new ConfiguredAspect.Builder(getName(), ruleContext)
         .addProvider(
             J2ObjcMappingFileProvider.class,
             new J2ObjcMappingFileProvider(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcProtoAspect.java
index 9f35a6a..cf94435 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcProtoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcProtoAspect.java
@@ -19,7 +19,6 @@
 import static com.google.devtools.build.lib.packages.BuildType.LABEL;
 
 import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.Constants;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
@@ -38,6 +37,11 @@
  * have not yet been released into open-source.
  */
 public class BazelJ2ObjcProtoAspect extends AbstractJ2ObjcProtoAspect {
+  public static final String NAME = "BazelJ2ObjcProtoAspect";
+
+  public BazelJ2ObjcProtoAspect(String toolsRepository) {
+    super(toolsRepository);
+  }
 
   @Override
   protected AspectDefinition.Builder addAdditionalAttributes(AspectDefinition.Builder builder) {
@@ -46,17 +50,17 @@
             .cfg(HOST)
             .exec()
             .value(Label.parseAbsoluteUnchecked(
-                Constants.TOOLS_REPOSITORY + "//tools/objc:compile_protos")))
+                toolsRepository + "//tools/objc:compile_protos")))
         .add(attr("$protoc_support_darwin", LABEL)
             .cfg(HOST)
             .exec()
             .value(Label.parseAbsoluteUnchecked(
-                Constants.TOOLS_REPOSITORY + "//tools/objc:proto_support")))
+                toolsRepository + "//tools/objc:proto_support")))
         .add(attr("$j2objc_plugin", LABEL)
             .cfg(HOST)
             .exec()
             .value(Label.parseAbsoluteUnchecked(
-                Constants.TOOLS_REPOSITORY + "//third_party/java/j2objc:proto_plugin")));
+                toolsRepository + "//third_party/java/j2objc:proto_plugin")));
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
index 3ff31cf..b8b941a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
@@ -24,11 +24,10 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.Constants;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ParameterFile;
 import com.google.devtools.build.lib.analysis.ConfiguredAspect;
-import com.google.devtools.build.lib.analysis.ConfiguredNativeAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
 import com.google.devtools.build.lib.analysis.RuleContext;
@@ -42,6 +41,7 @@
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
 import com.google.devtools.build.lib.rules.apple.AppleToolchain;
 import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
@@ -57,8 +57,15 @@
 /**
  * J2ObjC transpilation aspect for Java rules.
  */
-public class J2ObjcAspect implements ConfiguredNativeAspectFactory {
+public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectFactory {
   public static final String NAME = "J2ObjcAspect";
+  private final String toolsRepository;
+  private final BazelJ2ObjcProtoAspect bazelJ2ObjcProtoAspect;
+
+  public J2ObjcAspect(String toolsRepository, BazelJ2ObjcProtoAspect bazelJ2ObjcProtoAspect) {
+    this.toolsRepository = toolsRepository;
+    this.bazelJ2ObjcProtoAspect = bazelJ2ObjcProtoAspect;
+  }
 
   private static final Iterable<Attribute> DEPENDENT_ATTRIBUTES = ImmutableList.of(
       new Attribute("$jre_emul_lib", Mode.TARGET),
@@ -71,9 +78,9 @@
    */
   protected AspectDefinition.Builder addAdditionalAttributes(
       AspectDefinition.Builder builder) {
-    return builder.attributeAspect("deps", J2ObjcAspect.class, BazelJ2ObjcProtoAspect.class)
-        .attributeAspect("exports", J2ObjcAspect.class, BazelJ2ObjcProtoAspect.class)
-        .attributeAspect("runtime_deps", J2ObjcAspect.class, BazelJ2ObjcProtoAspect.class);
+    return builder.attributeAspect("deps", this, bazelJ2ObjcProtoAspect)
+        .attributeAspect("exports", this, bazelJ2ObjcProtoAspect)
+        .attributeAspect("runtime_deps", this, bazelJ2ObjcProtoAspect);
   }
 
   @Override
@@ -87,22 +94,22 @@
             ObjcConfiguration.class)
         .add(attr("$j2objc", LABEL).cfg(HOST).exec()
             .value(Label.parseAbsoluteUnchecked(
-                Constants.TOOLS_REPOSITORY + "//tools/j2objc:j2objc_deploy.jar")))
+                toolsRepository + "//tools/j2objc:j2objc_deploy.jar")))
         .add(attr("$j2objc_wrapper", LABEL)
             .allowedFileTypes(FileType.of(".py"))
             .cfg(HOST)
             .exec()
             .singleArtifact()
             .value(Label.parseAbsoluteUnchecked(
-                Constants.TOOLS_REPOSITORY + "//tools/j2objc:j2objc_wrapper")))
+                toolsRepository + "//tools/j2objc:j2objc_wrapper")))
         .add(attr("$jre_emul_jar", LABEL).cfg(HOST)
             .value(Label.parseAbsoluteUnchecked(
-                Constants.TOOLS_REPOSITORY + "//third_party/java/j2objc:jre_emul.jar")))
+                toolsRepository + "//third_party/java/j2objc:jre_emul.jar")))
         .add(attr("$jre_emul_lib", LABEL)
             .value(Label.parseAbsoluteUnchecked("//third_party/java/j2objc:jre_emul_lib")))
         .add(attr("$xcrunwrapper", LABEL).cfg(HOST).exec()
             .value(Label.parseAbsoluteUnchecked(
-                Constants.TOOLS_REPOSITORY + "//tools/objc:xcrunwrapper")))
+                toolsRepository + "//tools/objc:xcrunwrapper")))
         .add(attr(":xcode_config", LABEL)
             .allowedRuleClasses("xcode_config")
             .checkConstraints()
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspect.java
index cf102da..348ac6d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspect.java
@@ -17,26 +17,27 @@
 import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
 
 import com.google.devtools.build.lib.analysis.ConfiguredAspect;
-import com.google.devtools.build.lib.analysis.ConfiguredNativeAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.rules.proto.ProtoSourcesProvider;
 
 /**
  * Aspect that gathers the proto dependencies of the attached rule target, and propagates the proto
  * values of its dependencies through the ObjcProtoProvider.
  */
-public class ObjcProtoAspect implements ConfiguredNativeAspectFactory {
+public class ObjcProtoAspect extends NativeAspectClass implements ConfiguredAspectFactory {
   public static final String NAME = "ObjcProtoAspect";
 
   @Override
   public AspectDefinition getDefinition(AspectParameters aspectParameters) {
     return new AspectDefinition.Builder(NAME)
-        .attributeAspect("deps", ObjcProtoAspect.class)
+        .attributeAspect("deps", this)
         .requiresConfigurationFragments(ObjcConfiguration.class)
         .build();
   }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
index f37e5e2..d201d88 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -99,7 +99,7 @@
       if (skylarkImportLookupValue == null) {
         return null;
       }
-  
+
       Object skylarkValue = skylarkImportLookupValue.getEnvironmentExtension()
           .get(skylarkValueName);
       if (!(skylarkValue instanceof SkylarkAspect)) {
@@ -123,10 +123,9 @@
     AspectKey key = (AspectKey) skyKey.argument();
     ConfiguredAspectFactory aspectFactory;
     Aspect aspect;
-    if (key.getAspectClass() instanceof NativeAspectClass<?>) {
-      NativeAspectClass<?> nativeAspectClass = (NativeAspectClass<?>) key.getAspectClass();
-      aspectFactory =
-          (ConfiguredAspectFactory) nativeAspectClass.newInstance();
+    if (key.getAspectClass() instanceof NativeAspectClass) {
+      NativeAspectClass nativeAspectClass = (NativeAspectClass) key.getAspectClass();
+      aspectFactory = (ConfiguredAspectFactory) nativeAspectClass;
       aspect = Aspect.forNative(nativeAspectClass, key.getParameters());
     } else if (key.getAspectClass() instanceof SkylarkAspectClass) {
       SkylarkAspectClass skylarkAspectClass = (SkylarkAspectClass) key.getAspectClass();
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
index ee5b3b6..bdb273e 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
@@ -45,15 +45,11 @@
    * A dummy aspect factory. Is there to demonstrate how to define aspects and so that we can test
    * {@code attributeAspect}.
    */
-  public static final class TestAspectFactory implements ConfiguredNativeAspectFactory {
-    private final AspectDefinition definition;
+  public static final class TestAspectClass extends NativeAspectClass
+    implements ConfiguredAspectFactory {
+    private AspectDefinition definition;
 
-    /**
-     * Normal aspects will have an argumentless constructor and their definition will be hard-wired
-     * as a static member. This one is different so that we can create the definition in a test
-     * method.
-     */
-    private TestAspectFactory(AspectDefinition definition) {
+    public void setAspectDefinition(AspectDefinition definition) {
       this.definition = definition;
     }
 
@@ -69,6 +65,8 @@
     }
   }
 
+  public static final TestAspectClass TEST_ASPECT_CLASS = new TestAspectClass();
+
   @Test
   public void testAspectWithImplicitOrLateboundAttribute_AddsToAttributeMap() throws Exception {
     Attribute implicit = attr("$runtime", BuildType.LABEL)
@@ -120,13 +118,11 @@
   @Test
   public void testAttributeAspect_WrapsAndAddsToMap() throws Exception {
     AspectDefinition withAspects = new AspectDefinition.Builder("attribute_aspect")
-        .attributeAspect("srcs", TestAspectFactory.class)
-        .attributeAspect("deps", new NativeAspectClass<TestAspectFactory>(TestAspectFactory.class))
+        .attributeAspect("srcs", TEST_ASPECT_CLASS)
+        .attributeAspect("deps", TEST_ASPECT_CLASS)
         .build();
-    assertThat(withAspects.getAttributeAspects())
-        .containsEntry("srcs", new NativeAspectClass<TestAspectFactory>(TestAspectFactory.class));
-    assertThat(withAspects.getAttributeAspects())
-        .containsEntry("deps", new NativeAspectClass<TestAspectFactory>(TestAspectFactory.class));
+    assertThat(withAspects.getAttributeAspects()).containsEntry("srcs", TEST_ASPECT_CLASS);
+    assertThat(withAspects.getAttributeAspects()).containsEntry("deps", TEST_ASPECT_CLASS);
   }
 
   @Test
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
index 253ac66..8a518bf 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
@@ -38,6 +38,7 @@
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.packages.RuleClass;
 import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
 import com.google.devtools.build.lib.vfs.ModifiedFileSet;
@@ -234,7 +235,7 @@
       public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) {
         return builder
             .add(attr("foo", LABEL_LIST).legacyAllowAnyFileType()
-                .aspect(AspectWithEmptyLateBoundAttribute.class))
+                .aspect(ASPECT_WITH_EMPTY_LATE_BOUND_ATTRIBUTE))
             .build();
       }
 
@@ -245,7 +246,8 @@
       }
     }
 
-    public static class AspectWithEmptyLateBoundAttribute implements ConfiguredNativeAspectFactory {
+    public static class AspectWithEmptyLateBoundAttribute extends NativeAspectClass
+      implements ConfiguredAspectFactory {
       @Override
       public AspectDefinition getDefinition(AspectParameters params) {
         return new AspectDefinition.Builder("testaspect")
@@ -266,6 +268,8 @@
             .build();
       }
     }
+    public static final AspectWithEmptyLateBoundAttribute ASPECT_WITH_EMPTY_LATE_BOUND_ATTRIBUTE =
+        new AspectWithEmptyLateBoundAttribute();
   }
 
   /**
@@ -293,8 +297,8 @@
       @Override
       public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) {
         return builder
-            .add(attr("foo", LABEL_LIST).legacyAllowAnyFileType().aspect(
-                AspectThatRegistersAction.class))
+            .add(attr("foo", LABEL_LIST).legacyAllowAnyFileType()
+                .aspect(ASPECT_THAT_REGISTERS_ACTION))
             .add(attr(":action_listener", LABEL_LIST).cfg(HOST).value(ACTION_LISTENER))
             .build();
       }
@@ -306,7 +310,8 @@
       }
     }
 
-    public static class AspectThatRegistersAction implements ConfiguredNativeAspectFactory {
+    public static class AspectThatRegistersAction extends NativeAspectClass
+      implements ConfiguredAspectFactory {
       @Override
       public AspectDefinition getDefinition(AspectParameters params) {
         return new AspectDefinition.Builder("testaspect").build();
@@ -320,6 +325,8 @@
         return new ConfiguredAspect.Builder("testaspect", ruleContext).build();
       }
     }
+    private static final AspectThatRegistersAction ASPECT_THAT_REGISTERS_ACTION =
+        new AspectThatRegistersAction();
   }
 
   /**
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java
index 882b483..bcdb951 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java
@@ -16,11 +16,11 @@
 import com.google.common.testing.EqualsTester;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
+import com.google.devtools.build.lib.analysis.util.TestAspects;
 import com.google.devtools.build.lib.analysis.util.TestAspects.AttributeAspect;
 import com.google.devtools.build.lib.analysis.util.TestAspects.ExtraAttributeAspect;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.packages.AspectParameters;
-import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.skyframe.AspectValue;
 
 import org.junit.Test;
@@ -50,12 +50,9 @@
     AspectParameters i2 = new AspectParameters.Builder()
         .addAttribute("foo", "baz")
         .build();
-    NativeAspectClass<AttributeAspect> a1 =
-        new NativeAspectClass<AttributeAspect>(AttributeAspect.class);
-    NativeAspectClass<AttributeAspect> a1b =
-        new NativeAspectClass<AttributeAspect>(AttributeAspect.class);
-    NativeAspectClass<ExtraAttributeAspect> a2 =
-        new NativeAspectClass<ExtraAttributeAspect>(ExtraAttributeAspect.class);
+    AttributeAspect a1 = TestAspects.ATTRIBUTE_ASPECT;
+    AttributeAspect a1b = TestAspects.ATTRIBUTE_ASPECT;
+    ExtraAttributeAspect a2 = TestAspects.EXTRA_ATTRIBUTE_ASPECT;
 
     // label: //a:l1 or //a:l2
     // aspectConfiguration: target or host
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/DependencyResolverTest.java b/src/test/java/com/google/devtools/build/lib/analysis/DependencyResolverTest.java
index 13d31cc..c534f69 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/DependencyResolverTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/DependencyResolverTest.java
@@ -101,14 +101,13 @@
     update();
   }
 
-  private <T extends ConfiguredNativeAspectFactory>
-    ListMultimap<Attribute, Dependency> dependentNodeMap(
-      String targetName, Class<T> aspect) throws Exception {
+  private ListMultimap<Attribute, Dependency> dependentNodeMap(
+      String targetName, NativeAspectClass aspect) throws Exception {
     Target target = packageManager.getTarget(reporter, Label.parseAbsolute(targetName));
     return dependencyResolver.dependentNodeMap(
         new TargetAndConfiguration(target, getTargetConfiguration()),
         getHostConfiguration(),
-        aspect != null ? Aspect.forNative(new NativeAspectClass<T>(aspect)) : null,
+        aspect != null ? Aspect.forNative(aspect) : null,
         ImmutableSet.<ConfigMatchingProvider>of());
   }
 
@@ -148,7 +147,7 @@
     ListMultimap<Attribute, Dependency> map = dependentNodeMap("//a:a", null);
     assertDep(
         map, "foo", "//a:b",
-        new AspectDescriptor(new NativeAspectClass<>(TestAspects.SimpleAspect.class)));
+        new AspectDescriptor(TestAspects.SIMPLE_ASPECT));
   }
 
   @Test
@@ -158,10 +157,10 @@
         "simple(name='a', foo=[':b'])",
         "simple(name='b', foo=[])");
     ListMultimap<Attribute, Dependency> map =
-        dependentNodeMap("//a:a", TestAspects.AttributeAspect.class);
+        dependentNodeMap("//a:a", TestAspects.ATTRIBUTE_ASPECT);
     assertDep(
         map, "foo", "//a:b",
-        new AspectDescriptor(new NativeAspectClass<>(TestAspects.AttributeAspect.class)));
+        new AspectDescriptor(TestAspects.ATTRIBUTE_ASPECT));
   }
 
   @Test
@@ -170,7 +169,7 @@
     pkg("a", "base(name='a')");
     pkg("extra", "base(name='extra')");
     ListMultimap<Attribute, Dependency> map =
-        dependentNodeMap("//a:a", TestAspects.ExtraAttributeAspect.class);
+        dependentNodeMap("//a:a", TestAspects.EXTRA_ATTRIBUTE_ASPECT);
     assertDep(map, "$dep", "//extra:extra");
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/DependencyTest.java b/src/test/java/com/google/devtools/build/lib/analysis/DependencyTest.java
index 0e4908d..e2b0fa7 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/DependencyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/DependencyTest.java
@@ -23,12 +23,8 @@
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
 import com.google.devtools.build.lib.analysis.util.TestAspects;
-import com.google.devtools.build.lib.analysis.util.TestAspects.AttributeAspect;
-import com.google.devtools.build.lib.analysis.util.TestAspects.SimpleAspect;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
-import com.google.devtools.build.lib.packages.NativeAspectClass;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -84,10 +80,8 @@
   @Test
   public void withConfigurationAndAspects_BasicAccessors() throws Exception {
     update();
-    AspectDescriptor simpleAspect = new AspectDescriptor(
-        new NativeAspectClass<SimpleAspect>(SimpleAspect.class));
-    AspectDescriptor attributeAspect = new AspectDescriptor(
-        new NativeAspectClass<AttributeAspect>(AttributeAspect.class));
+    AspectDescriptor simpleAspect = new AspectDescriptor(TestAspects.SIMPLE_ASPECT);
+    AspectDescriptor attributeAspect = new AspectDescriptor(TestAspects.ATTRIBUTE_ASPECT);
     ImmutableSet<AspectDescriptor> twoAspects = ImmutableSet.of(simpleAspect, attributeAspect);
     Dependency targetDep =
         Dependency.withConfigurationAndAspects(
@@ -130,10 +124,8 @@
   public void withConfigurationAndAspects_RejectsNullConfigWithNPE() throws Exception {
     // Although the NullPointerTester should check this, this test invokes a different code path,
     // because it includes aspects (which the NPT test will not).
-    AspectDescriptor simpleAspect = new AspectDescriptor(
-        new NativeAspectClass<SimpleAspect>(SimpleAspect.class));
-    AspectDescriptor attributeAspect = new AspectDescriptor(
-        new NativeAspectClass<AttributeAspect>(AttributeAspect.class));
+    AspectDescriptor simpleAspect = new AspectDescriptor(TestAspects.SIMPLE_ASPECT);
+    AspectDescriptor attributeAspect = new AspectDescriptor(TestAspects.ATTRIBUTE_ASPECT);
     ImmutableSet<AspectDescriptor> twoAspects = ImmutableSet.of(simpleAspect, attributeAspect);
 
     try {
@@ -160,10 +152,8 @@
   @Test
   public void withConfiguredAspects_BasicAccessors() throws Exception {
     update();
-    AspectDescriptor simpleAspect = new AspectDescriptor(
-        new NativeAspectClass<TestAspects.SimpleAspect>(TestAspects.SimpleAspect.class));
-    AspectDescriptor attributeAspect = new AspectDescriptor(
-        new NativeAspectClass<AttributeAspect>(AttributeAspect.class));
+    AspectDescriptor simpleAspect = new AspectDescriptor(TestAspects.SIMPLE_ASPECT);
+    AspectDescriptor attributeAspect = new AspectDescriptor(TestAspects.ATTRIBUTE_ASPECT);
     ImmutableMap<AspectDescriptor, BuildConfiguration> twoAspectMap = ImmutableMap.of(
         simpleAspect, getTargetConfiguration(), attributeAspect, getHostConfiguration());
     Dependency targetDep =
@@ -200,10 +190,8 @@
 
   @Test
   public void withTransitionAndAspects_BasicAccessors() throws Exception {
-    AspectDescriptor simpleAspect = new AspectDescriptor(
-        new NativeAspectClass<>(SimpleAspect.class));
-    AspectDescriptor attributeAspect = new AspectDescriptor(
-        new NativeAspectClass<>(AttributeAspect.class));
+    AspectDescriptor simpleAspect = new AspectDescriptor(TestAspects.SIMPLE_ASPECT);
+    AspectDescriptor attributeAspect = new AspectDescriptor(TestAspects.ATTRIBUTE_ASPECT);
     ImmutableSet<AspectDescriptor> twoAspects = ImmutableSet.of(simpleAspect, attributeAspect);
     Dependency hostDep =
         Dependency.withTransitionAndAspects(
@@ -262,12 +250,9 @@
     BuildConfiguration host = getHostConfiguration();
     BuildConfiguration target = getTargetConfiguration();
 
-    AspectDescriptor simpleAspect = new AspectDescriptor(
-        new NativeAspectClass<>(TestAspects.SimpleAspect.class));
-    AspectDescriptor attributeAspect = new AspectDescriptor(
-        new NativeAspectClass<>(TestAspects.AttributeAspect.class));
-    AspectDescriptor errorAspect = new AspectDescriptor(
-        new NativeAspectClass<>(TestAspects.ErrorAspect.class));
+    AspectDescriptor simpleAspect = new AspectDescriptor(TestAspects.SIMPLE_ASPECT);
+    AspectDescriptor attributeAspect = new AspectDescriptor(TestAspects.ATTRIBUTE_ASPECT);
+    AspectDescriptor errorAspect = new AspectDescriptor(TestAspects.ERROR_ASPECT);
 
     ImmutableSet<AspectDescriptor> twoAspects = ImmutableSet.of(simpleAspect, attributeAspect);
     ImmutableSet<AspectDescriptor> inverseAspects = ImmutableSet.of(attributeAspect, simpleAspect);
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
index 994ab41..3376a21 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
@@ -52,7 +52,6 @@
 import com.google.devtools.build.lib.analysis.BuildView;
 import com.google.devtools.build.lib.analysis.BuildView.AnalysisResult;
 import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment;
-import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredAttributeMapper;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
@@ -548,7 +547,7 @@
     return getGeneratingSpawnAction(
         Iterables.find(getFilesToBuild(target), artifactNamed(outputName)));
   }
- 
+
   protected void simulateLoadingPhase() {
     try {
       ensureTargetsVisited(targetConfig.getAllLabels().values());
@@ -922,7 +921,7 @@
    * is creating an Artifact.
    */
   protected Artifact getBinArtifact(String packageRelativePath, ConfiguredTarget owner,
-      Class<? extends ConfiguredAspectFactory> creatingAspectFactory) {
+      NativeAspectClass creatingAspectFactory) {
     return getPackageRelativeDerivedArtifact(
         packageRelativePath,
         owner.getConfiguration().getBinDirectory(),
@@ -931,7 +930,7 @@
                     owner.getLabel(),
                     owner.getConfiguration(),
                     owner.getConfiguration(),
-                    new NativeAspectClass(creatingAspectFactory),
+                    creatingAspectFactory,
                     AspectParameters.EMPTY)
                 .argument());
   }
@@ -988,7 +987,7 @@
    * is creating an Artifact.
    */
   protected Artifact getGenfilesArtifact(String packageRelativePath, ConfiguredTarget owner,
-      Class<? extends ConfiguredAspectFactory> creatingAspectFactory) {
+      NativeAspectClass creatingAspectFactory) {
     return getGenfilesArtifact(
         packageRelativePath, owner, creatingAspectFactory, AspectParameters.EMPTY);
   }
@@ -996,7 +995,7 @@
   protected Artifact getGenfilesArtifact(
       String packageRelativePath,
       ConfiguredTarget owner,
-      Class<? extends ConfiguredAspectFactory> creatingAspectFactory,
+      NativeAspectClass creatingAspectFactory,
       AspectParameters params) {
     return getPackageRelativeDerivedArtifact(
         packageRelativePath,
@@ -1006,7 +1005,7 @@
                     owner.getLabel(),
                     owner.getConfiguration(),
                     owner.getConfiguration(),
-                    new NativeAspectClass(creatingAspectFactory),
+                    creatingAspectFactory,
                     params)
                 .argument());
   }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
index 7d1a959..dc5a02a 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
@@ -27,7 +27,7 @@
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.ConfiguredAspect;
-import com.google.devtools.build.lib.analysis.ConfiguredNativeAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
@@ -48,6 +48,7 @@
 import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel;
 import com.google.devtools.build.lib.packages.AttributeMap;
+import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.packages.RuleClass;
 import com.google.devtools.build.lib.packages.RuleClass.Builder;
@@ -148,7 +149,8 @@
   /**
    * A base class for mock aspects to reduce boilerplate.
    */
-  public abstract static class BaseAspect implements ConfiguredNativeAspectFactory {
+  public abstract static class BaseAspect extends NativeAspectClass
+    implements ConfiguredAspectFactory {
     @Override
     public ConfiguredAspect create(
         ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters) {
@@ -164,7 +166,8 @@
     }
   }
 
-  private static final AspectDefinition SIMPLE_ASPECT =
+  public static final SimpleAspect SIMPLE_ASPECT = new SimpleAspect();
+  private static final AspectDefinition SIMPLE_ASPECT_DEFINITION =
       new AspectDefinition.Builder("simple").build();
 
   /**
@@ -173,16 +176,19 @@
   public static class SimpleAspect extends BaseAspect {
     @Override
     public AspectDefinition getDefinition(AspectParameters aspectParameters) {
-      return SIMPLE_ASPECT;
+      return SIMPLE_ASPECT_DEFINITION;
     }
   }
 
-  private static final AspectDefinition EXTRA_ATTRIBUTE_ASPECT =
+  public static final ExtraAttributeAspect EXTRA_ATTRIBUTE_ASPECT = new ExtraAttributeAspect();
+  private static final AspectDefinition EXTRA_ATTRIBUTE_ASPECT_DEFINITION =
       new AspectDefinition.Builder("extra_attribute")
           .add(attr("$dep", LABEL).value(Label.parseAbsoluteUnchecked("//extra:extra")))
           .build();
 
-  private static final AspectDefinition EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER =
+  private static final ExtraAttributeAspectRequiringProvider
+    EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER = new ExtraAttributeAspectRequiringProvider();
+  private static final AspectDefinition EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER_DEFINITION =
       new AspectDefinition.Builder("extra_attribute_with_provider")
           .add(attr("$dep", LABEL).value(Label.parseAbsoluteUnchecked("//extra:extra")))
           .requireProvider(RequiredProvider.class)
@@ -194,12 +200,14 @@
   public static class ExtraAttributeAspect extends BaseAspect {
     @Override
     public AspectDefinition getDefinition(AspectParameters aspectParameters) {
-      return EXTRA_ATTRIBUTE_ASPECT;
+      return EXTRA_ATTRIBUTE_ASPECT_DEFINITION;
     }
   }
 
-  private static final AspectDefinition ATTRIBUTE_ASPECT = new AspectDefinition.Builder("attribute")
-      .attributeAspect("foo", AttributeAspect.class)
+  public static final AttributeAspect ATTRIBUTE_ASPECT = new AttributeAspect();
+  private static final AspectDefinition ATTRIBUTE_ASPECT_DEFINITION =
+      new AspectDefinition.Builder("attribute")
+      .attributeAspect("foo", ATTRIBUTE_ASPECT)
       .build();
 
   /**
@@ -208,7 +216,7 @@
   public static class AttributeAspect extends BaseAspect {
     @Override
     public AspectDefinition getDefinition(AspectParameters aspectParameters) {
-      return ATTRIBUTE_ASPECT;
+      return ATTRIBUTE_ASPECT_DEFINITION;
     }
   }
 
@@ -218,27 +226,28 @@
   public static class ExtraAttributeAspectRequiringProvider extends BaseAspect {
     @Override
     public AspectDefinition getDefinition(AspectParameters aspectParameters) {
-      return EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER;
+      return EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER_DEFINITION;
     }
   }
 
   public static class AspectRequiringProvider extends BaseAspect {
     @Override
     public AspectDefinition getDefinition(AspectParameters aspectParameters) {
-      return ASPECT_REQUIRING_PROVIDER;
+      return ASPECT_REQUIRING_PROVIDER_DEFINITION;
     }
   }
 
   /**
    * An aspect that has a definition depending on parameters provided by originating rule.
    */
-  public static class ParametrizedDefinitionAspect implements ConfiguredNativeAspectFactory {
+  public static class ParametrizedDefinitionAspect extends NativeAspectClass
+    implements ConfiguredAspectFactory {
 
     @Override
     public AspectDefinition getDefinition(AspectParameters aspectParameters) {
       AspectDefinition.Builder builder =
           new AspectDefinition.Builder("parametrized_definition_aspect")
-              .attributeAspect("foo", ParametrizedDefinitionAspect.class);
+              .attributeAspect("foo", this);
       ImmutableCollection<String> baz = aspectParameters.getAttribute("baz");
       if (baz != null) {
         try {
@@ -274,8 +283,12 @@
     }
   }
 
+  private static final ParametrizedDefinitionAspect PARAMETRIZED_DEFINITION_ASPECT =
+      new ParametrizedDefinitionAspect();
 
-  private static final AspectDefinition ASPECT_REQUIRING_PROVIDER =
+  private static final AspectRequiringProvider ASPECT_REQUIRING_PROVIDER =
+      new AspectRequiringProvider();
+  private static final AspectDefinition ASPECT_REQUIRING_PROVIDER_DEFINITION =
       new AspectDefinition.Builder("requiring_provider")
           .requireProvider(RequiredProvider.class)
           .build();
@@ -283,7 +296,9 @@
   /**
    * An aspect that raises an error.
    */
-  public static class ErrorAspect implements ConfiguredNativeAspectFactory {
+  public static class ErrorAspect extends NativeAspectClass
+    implements ConfiguredAspectFactory {
+
     @Override
     public ConfiguredAspect create(
         ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters) {
@@ -293,12 +308,14 @@
 
     @Override
     public AspectDefinition getDefinition(AspectParameters aspectParameters) {
-      return ERROR_ASPECT;
+      return ERROR_ASPECT_DEFINITION;
     }
   }
 
-  private static final AspectDefinition ERROR_ASPECT = new AspectDefinition.Builder("error")
-      .attributeAspect("bar", ErrorAspect.class)
+  public static final ErrorAspect ERROR_ASPECT = new ErrorAspect();
+  private static final AspectDefinition ERROR_ASPECT_DEFINITION =
+      new AspectDefinition.Builder("error")
+      .attributeAspect("bar", ERROR_ASPECT)
       .build();
 
   /**
@@ -341,9 +358,9 @@
     public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
       return builder
           .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
-              .aspect(SimpleAspect.class))
+              .aspect(SIMPLE_ASPECT))
           .add(attr("bar", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
-              .aspect(SimpleAspect.class))
+              .aspect(SIMPLE_ASPECT))
           .build();
 
     }
@@ -363,7 +380,7 @@
    */
   public static class AspectRequiringProviderRule implements RuleDefinition {
 
-    private static final class TestAspectParametersExtractor implements 
+    private static final class TestAspectParametersExtractor implements
         Function<Rule, AspectParameters> {
       @Override
       public AspectParameters apply(Rule rule) {
@@ -381,7 +398,7 @@
     public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
       return builder
           .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
-              .aspect(AspectRequiringProvider.class, new TestAspectParametersExtractor()))
+              .aspect(ASPECT_REQUIRING_PROVIDER, new TestAspectParametersExtractor()))
           .add(attr("baz", STRING))
           .build();
 
@@ -422,7 +439,7 @@
           .add(
               attr("foo", LABEL_LIST)
                   .allowedFileTypes(FileTypeSet.ANY_FILE)
-                  .aspect(ParametrizedDefinitionAspect.class, new TestAspectParametersExtractor()))
+                  .aspect(PARAMETRIZED_DEFINITION_ASPECT, new TestAspectParametersExtractor()))
           .add(attr("baz", STRING))
           .build();
     }
@@ -445,7 +462,7 @@
     public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
       return builder
           .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
-              .aspect(ExtraAttributeAspectRequiringProvider.class))
+              .aspect(EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER))
           .build();
 
     }
@@ -468,7 +485,7 @@
     public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
       return builder
           .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
-              .aspect(ErrorAspect.class))
+              .aspect(ERROR_ASPECT))
           .add(attr("bar", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
           .build();
     }
diff --git a/src/test/java/com/google/devtools/build/lib/packages/AttributeTest.java b/src/test/java/com/google/devtools/build/lib/packages/AttributeTest.java
index 07d5a28..c6d7ce2 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/AttributeTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/AttributeTest.java
@@ -219,7 +219,7 @@
         attr("x", LABEL_LIST)
             .allowedFileTypes(txtFiles)
             .mandatory()
-            .aspect(TestAspects.SimpleAspect.class)
+            .aspect(TestAspects.SIMPLE_ASPECT)
             .build();
 
     {
@@ -238,7 +238,7 @@
               .cloneBuilder()
               .nonEmpty()
               .allowedRuleClasses(ruleClasses)
-              .aspect(TestAspects.ErrorAspect.class)
+              .aspect(TestAspects.ERROR_ASPECT)
               .build();
       assertEquals("x", childAttr2.getName());
       assertEquals(txtFiles, childAttr2.getAllowedFileTypesPredicate());