You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by mm...@apache.org on 2022/05/26 08:56:44 UTC

[ignite-extensions] branch master updated: IGNITE-17033 Move ignite-aop to the Ignite Extensions (#144)

This is an automated email from the ASF dual-hosted git repository.

mmuzaf pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite-extensions.git


The following commit(s) were added to refs/heads/master by this push:
     new 08428c9  IGNITE-17033 Move ignite-aop to the Ignite Extensions (#144)
08428c9 is described below

commit 08428c9d179a58ef549b39c24f2cb2c507ea6a09
Author: Maxim Muzafarov <ma...@gmail.com>
AuthorDate: Thu May 26 11:56:39 2022 +0300

    IGNITE-17033 Move ignite-aop to the Ignite Extensions (#144)
---
 modules/aop-ext/README.txt                         |  33 +
 modules/aop-ext/assembly/aop-ext.xml               |  34 +
 modules/aop-ext/licenses/apache-2.0.txt            | 202 ++++++
 .../modules/core/src/test/config/log4j-test.xml    |  57 ++
 .../modules/core/src/test/config/tests.properties  |  16 +
 modules/aop-ext/pom.xml                            | 136 ++++
 .../gridify/aop/aspectj/GridifyAspectJAspect.java  | 133 ++++
 .../aop/aspectj/GridifySetToSetAspectJAspect.java  | 145 ++++
 .../aspectj/GridifySetToValueAspectJAspect.java    | 145 ++++
 .../compute/gridify/aop/aspectj/package-info.java  |  23 +
 .../aop/spring/GridifySetToSetSpringAspect.java    | 139 ++++
 .../aop/spring/GridifySetToValueSpringAspect.java  | 139 ++++
 .../gridify/aop/spring/GridifySpringAspect.java    | 127 ++++
 .../gridify/aop/spring/GridifySpringEnhancer.java  |  82 +++
 .../gridify/aop/spring/GridifySpringPointcut.java  | 136 ++++
 .../compute/gridify/aop/spring/package-info.java   |  23 +
 .../src/test/config/aop/aspectj/META-INF/aop.xml   | 306 ++++++++
 .../org/apache/ignite/gridify/AbstractAopTest.java | 778 +++++++++++++++++++++
 .../apache/ignite/gridify/BasicAopSelfTest.java    |  75 ++
 .../ignite/gridify/GridifySetToSetTarget.java      | 378 ++++++++++
 .../gridify/GridifySetToSetTargetInterface.java    | 112 +++
 .../ignite/gridify/GridifySetToValueTarget.java    | 203 ++++++
 .../gridify/GridifySetToValueTargetInterface.java  | 102 +++
 .../GridifySetToXXXNonSpringAopSelfTest.java       | 212 ++++++
 .../gridify/GridifySetToXXXSpringAopSelfTest.java  | 213 ++++++
 .../ignite/gridify/NonSpringAopSelfTest.java       |  57 ++
 .../apache/ignite/gridify/SpringAopSelfTest.java   |  52 ++
 .../org/apache/ignite/gridify/TestAopTarget.java   | 138 ++++
 .../ignite/gridify/TestAopTargetInterface.java     |  86 +++
 .../ignite/gridify/TestGridifyException.java       |  38 +
 .../org/apache/ignite/gridify/TestGridifyJob.java  |  66 ++
 .../org/apache/ignite/gridify/TestGridifyTask.java |  50 ++
 .../gridify/hierarchy/GridifyHierarchyTest.java    |  53 ++
 .../ignite/gridify/hierarchy/SuperTarget.java      |  52 ++
 .../apache/ignite/gridify/hierarchy/Target.java    |  45 ++
 .../ignite/gridify/hierarchy/package-info.java     |  23 +
 .../org/apache/ignite/gridify/package-info.java    |  23 +
 .../apache/ignite/gridify/test_resource.properties |  18 +
 .../optimized/OptimizedMarshallerAopTest.java      |  99 +++
 .../org/apache/ignite/p2p/P2PGridifySelfTest.java  | 254 +++++++
 .../ignite/testsuites/IgniteAopSelfTestSuite.java  |  62 ++
 .../singlesplit/SingleSplitTestJobTarget.java      |  44 ++
 .../direct/singlesplit/SingleSplitTestTask.java    | 104 +++
 .../direct/singlesplit/SingleSplitsLoadTest.java   | 134 ++++
 .../loadtests/direct/singlesplit/package-info.java |  23 +
 .../gridify/GridifyLoadTestJobTarget.java          |  37 +
 .../loadtests/gridify/GridifyLoadTestTask.java     |  74 ++
 .../gridify/GridifySingleSplitLoadTest.java        | 157 +++++
 .../java/org/test/gridify/ExternalAopTarget.java   | 134 ++++
 .../org/test/gridify/ExternalGridifyException.java |  38 +
 .../java/org/test/gridify/ExternalGridifyTask.java |  83 +++
 .../test/gridify/ExternalNonSpringAopSelfTest.java | 570 +++++++++++++++
 .../test/java/org/test/gridify/package-info.java   |  23 +
 .../java/org/test/gridify/test_resource.properties |  20 +
 pom.xml                                            |   1 +
 55 files changed, 6507 insertions(+)

diff --git a/modules/aop-ext/README.txt b/modules/aop-ext/README.txt
new file mode 100644
index 0000000..38c77de
--- /dev/null
+++ b/modules/aop-ext/README.txt
@@ -0,0 +1,33 @@
+Apache Ignite AOP Module
+------------------------
+
+Apache Ignite AOP module provides capability to turn any Java method to a distributed closure by
+adding @Gridify annotation to it.
+
+To enable AOP module when starting a standalone node, move 'optional/ignite-aop' folder to
+'libs' folder before running 'ignite.{sh|bat}' script. The content of the module folder will
+be added to classpath in this case.
+
+Importing AOP Module In Maven Project
+-------------------------------------
+
+If you are using Maven to manage dependencies of your project, you can add AOP module
+dependency like this (replace '${ignite.version}' with actual Ignite version you are
+interested in):
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                        http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    ...
+    <dependencies>
+        ...
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-aop-ext</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        ...
+    </dependencies>
+    ...
+</project>
diff --git a/modules/aop-ext/assembly/aop-ext.xml b/modules/aop-ext/assembly/aop-ext.xml
new file mode 100644
index 0000000..0c28f4c
--- /dev/null
+++ b/modules/aop-ext/assembly/aop-ext.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
+          http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+    <id>bin</id>
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <componentDescriptors>
+        <componentDescriptor>../../assembly/bin-component-shared.xml</componentDescriptor>
+    </componentDescriptors>
+</assembly>
diff --git a/modules/aop-ext/licenses/apache-2.0.txt b/modules/aop-ext/licenses/apache-2.0.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/modules/aop-ext/licenses/apache-2.0.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/modules/aop-ext/modules/core/src/test/config/log4j-test.xml b/modules/aop-ext/modules/core/src/test/config/log4j-test.xml
new file mode 100644
index 0000000..cc2146e
--- /dev/null
+++ b/modules/aop-ext/modules/core/src/test/config/log4j-test.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN"
+    "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+        <param name="Target" value="System.out"/>
+        <param name="Threshold" value="DEBUG"/>
+
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="[%d{ISO8601}][%-5p][%t][%c{1}] %m%n"/>
+        </layout>
+
+        <filter class="org.apache.log4j.varia.LevelRangeFilter">
+            <param name="levelMin" value="DEBUG"/>
+            <param name="levelMax" value="INFO"/>
+        </filter>
+    </appender>
+
+    <appender name="CONSOLE_ERR" class="org.apache.log4j.ConsoleAppender">
+        <param name="Target" value="System.err"/>
+
+        <param name="Threshold" value="WARN"/>
+
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="[%d{ISO8601}][%-5p][%t][%c{1}] %m%n"/>
+        </layout>
+    </appender>
+
+    <category name="org">
+        <level value="INFO"/>
+    </category>
+
+    <root>
+        <level value="INFO"/>
+
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="CONSOLE_ERR"/>
+    </root>
+</log4j:configuration>
diff --git a/modules/aop-ext/modules/core/src/test/config/tests.properties b/modules/aop-ext/modules/core/src/test/config/tests.properties
new file mode 100644
index 0000000..86094c8
--- /dev/null
+++ b/modules/aop-ext/modules/core/src/test/config/tests.properties
@@ -0,0 +1,16 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
diff --git a/modules/aop-ext/pom.xml b/modules/aop-ext/pom.xml
new file mode 100644
index 0000000..84b2194
--- /dev/null
+++ b/modules/aop-ext/pom.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<!--
+    POM file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ignite</groupId>
+        <artifactId>ignite-parent-ext-internal</artifactId>
+        <version>1</version>
+        <relativePath>../../parent-internal/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>ignite-aop-ext</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <url>https://ignite.apache.org</url>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ignite-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjrt</artifactId>
+            <version>${aspectj.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <version>${aspectj.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aop</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <version>${spring.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>aopalliance</groupId>
+            <artifactId>aopalliance</artifactId>
+            <version>1.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ignite-log4j</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ignite-core</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <testResources>
+            <testResource>
+                <directory>src/test/config/aop/aspectj</directory>
+            </testResource>
+
+            <testResource>
+                <directory>src/test/java</directory>
+                <excludes>
+                    <exclude>**/*.java</exclude>
+                </excludes>
+            </testResource>
+        </testResources>
+
+        <plugins>
+            <!-- Generate the OSGi MANIFEST.MF for this bundle. -->
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <forkMode>pertest</forkMode>
+                    <argLine>-javaagent:${basedir}/target/libs/aspectjweaver-${aspectj.version}.jar</argLine>
+                    <workingDirectory>${basedir}/target</workingDirectory>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <version>2.8.2</version>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/GridifyAspectJAspect.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/GridifyAspectJAspect.java
new file mode 100644
index 0000000..24dd523
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/GridifyAspectJAspect.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.compute.gridify.aop.aspectj;
+
+import java.lang.reflect.Method;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.compute.gridify.Gridify;
+import org.apache.ignite.compute.gridify.GridifyArgument;
+import org.apache.ignite.compute.gridify.GridifyInterceptor;
+import org.apache.ignite.compute.gridify.GridifyRuntimeException;
+import org.apache.ignite.compute.gridify.aop.GridifyArgumentAdapter;
+import org.apache.ignite.compute.gridify.aop.GridifyDefaultTask;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.G;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+
+import static org.apache.ignite.IgniteState.STARTED;
+
+/**
+ * AspectJ aspect that cross-cuts on all methods grid-enabled with
+ * {@link org.apache.ignite.compute.gridify.Gridify} annotation and potentially executes them on
+ * remote node.
+ * <p>
+ * See {@link org.apache.ignite.compute.gridify.Gridify} documentation for more information about execution of
+ * {@code gridified} methods.
+ * @see org.apache.ignite.compute.gridify.Gridify
+ */
+@Aspect
+public class GridifyAspectJAspect {
+    /**
+     * Aspect implementation which executes grid-enabled methods on remote
+     * nodes.
+     *
+     * @param joinPnt Join point provided by AspectJ AOP.
+     * @return Method execution result.
+     * @throws Throwable If execution failed.
+     */
+    @SuppressWarnings({"ProhibitedExceptionDeclared", "ProhibitedExceptionThrown", "unchecked"})
+    @Around("execution(@org.apache.ignite.compute.gridify.Gridify * *(..)) && !cflow(call(* org.apache.ignite.compute.ComputeJob.*(..)))")
+    public Object gridify(ProceedingJoinPoint joinPnt) throws Throwable {
+        Method mtd = ((MethodSignature)joinPnt.getSignature()).getMethod();
+
+        Gridify ann = mtd.getAnnotation(Gridify.class);
+
+        assert ann != null : "Intercepted method does not have gridify annotation.";
+
+        // Since annotations in Java don't allow 'null' as default value
+        // we have accept an empty string and convert it here.
+        // NOTE: there's unintended behavior when user specifies an empty
+        // string as intended Ignite instance name.
+        // NOTE: the 'ann.igniteInstanceName() == null' check is added to mitigate
+        // annotation bugs in some scripting languages (e.g. Groovy).
+        String igniteInstanceName = F.isEmpty(ann.igniteInstanceName()) ? ann.gridName() : ann.igniteInstanceName();
+
+        if (F.isEmpty(igniteInstanceName))
+            igniteInstanceName = null;
+
+        if (G.state(igniteInstanceName) != STARTED)
+            throw new IgniteCheckedException("Grid is not locally started: " + igniteInstanceName);
+
+        // Initialize defaults.
+        GridifyArgument arg = new GridifyArgumentAdapter(mtd.getDeclaringClass(), mtd.getName(),
+                mtd.getParameterTypes(), joinPnt.getArgs(), joinPnt.getTarget());
+
+        if (!ann.interceptor().equals(GridifyInterceptor.class)) {
+            // Check interceptor first.
+            if (!ann.interceptor().newInstance().isGridify(ann, arg))
+                return joinPnt.proceed();
+        }
+
+        if (!ann.taskClass().equals(GridifyDefaultTask.class) && !ann.taskName().isEmpty()) {
+            throw new IgniteCheckedException("Gridify annotation must specify either Gridify.taskName() or " +
+                "Gridify.taskClass(), but not both: " + ann);
+        }
+
+        try {
+            Ignite ignite = G.ignite(igniteInstanceName);
+
+            // If task class was specified.
+            if (!ann.taskClass().equals(GridifyDefaultTask.class)) {
+                return ignite.compute().withTimeout(ann.timeout()).execute(
+                    (Class<? extends ComputeTask<GridifyArgument, Object>>)ann.taskClass(), arg);
+            }
+
+            // If task name was not specified.
+            if (ann.taskName().isEmpty()) {
+                return ignite.compute().withTimeout(ann.timeout()).execute(new GridifyDefaultTask(
+                    joinPnt.getSignature().getDeclaringType()), arg);
+            }
+
+            // If task name was specified.
+            return ignite.compute().withTimeout(ann.timeout()).execute(ann.taskName(), arg);
+        }
+        catch (Exception e) {
+            for (Class<?> ex : ((MethodSignature)joinPnt.getSignature()).getMethod().getExceptionTypes()) {
+                // Descend all levels down.
+                Throwable cause = e.getCause();
+
+                while (cause != null) {
+                    if (ex.isAssignableFrom(cause.getClass()))
+                        throw cause;
+
+                    cause = cause.getCause();
+                }
+
+                if (ex.isAssignableFrom(e.getClass()))
+                    throw e;
+            }
+
+            throw new GridifyRuntimeException("Undeclared exception thrown: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/GridifySetToSetAspectJAspect.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/GridifySetToSetAspectJAspect.java
new file mode 100644
index 0000000..653f057
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/GridifySetToSetAspectJAspect.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.compute.gridify.aop.aspectj;
+
+import java.lang.reflect.Method;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.compute.gridify.GridifyInterceptor;
+import org.apache.ignite.compute.gridify.GridifyNodeFilter;
+import org.apache.ignite.compute.gridify.GridifyRuntimeException;
+import org.apache.ignite.compute.gridify.GridifySetToSet;
+import org.apache.ignite.compute.gridify.aop.GridifySetToSetAbstractAspect;
+import org.apache.ignite.internal.util.gridify.GridifyArgumentBuilder;
+import org.apache.ignite.internal.util.gridify.GridifyRangeArgument;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.G;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+
+import static org.apache.ignite.IgniteState.STARTED;
+import static org.apache.ignite.internal.util.gridify.GridifyUtils.UNKNOWN_SIZE;
+
+/**
+ * AspectJ aspect that cross-cuts on all methods grid-enabled with
+ * {@link GridifySetToSet} annotation and potentially executes them on
+ * remote node.
+ * <p>
+ * See {@link GridifySetToSet} documentation for more information about execution of
+ * {@code gridified} methods.
+ * @see GridifySetToSet
+ */
+@Aspect
+public class GridifySetToSetAspectJAspect extends GridifySetToSetAbstractAspect {
+    /**
+     * Aspect implementation which executes grid-enabled methods on remote
+     * nodes.
+     *
+     * @param joinPnt Join point provided by AspectJ AOP.
+     * @return Method execution result.
+     * @throws Throwable If execution failed.
+     */
+    @SuppressWarnings({"ProhibitedExceptionDeclared", "ProhibitedExceptionThrown"})
+    @Around("execution(@org.apache.ignite.compute.gridify.GridifySetToSet * *(..)) && " +
+        "!cflow(call(* org.apache.ignite.compute.ComputeJob.*(..)))")
+    public Object gridify(ProceedingJoinPoint joinPnt) throws Throwable {
+        Method mtd = ((MethodSignature)joinPnt.getSignature()).getMethod();
+
+        GridifySetToSet ann = mtd.getAnnotation(GridifySetToSet.class);
+
+        assert ann != null : "Intercepted method does not have gridify annotation.";
+
+        // Since annotations in Java don't allow 'null' as default value
+        // we have accept an empty string and convert it here.
+        // NOTE: there's unintended behavior when user specifies an empty
+        // string as intended Ignite instance name.
+        // NOTE: the 'ann.igniteInstanceName() == null' check is added to mitigate
+        // annotation bugs in some scripting languages (e.g. Groovy).
+        String igniteInstanceName = F.isEmpty(ann.igniteInstanceName()) ? ann.gridName() : ann.igniteInstanceName();
+
+        if (F.isEmpty(igniteInstanceName))
+            igniteInstanceName = null;
+
+        if (G.state(igniteInstanceName) != STARTED)
+            throw new IgniteCheckedException("Grid is not locally started: " + igniteInstanceName);
+
+        GridifyNodeFilter nodeFilter = null;
+
+        if (!ann.nodeFilter().equals(GridifyNodeFilter.class))
+            nodeFilter = ann.nodeFilter().newInstance();
+
+        // Check method return type.
+        checkMethodSignature(mtd);
+
+        GridifyArgumentBuilder argBuilder = new GridifyArgumentBuilder();
+
+        // Creates task argument.
+        GridifyRangeArgument arg = argBuilder.createTaskArgument(
+            mtd.getDeclaringClass(),
+            mtd.getName(),
+            mtd.getReturnType(),
+            mtd.getParameterTypes(),
+            mtd.getParameterAnnotations(),
+            joinPnt.getArgs(),
+            joinPnt.getTarget());
+
+        if (!ann.interceptor().equals(GridifyInterceptor.class)) {
+            // Check interceptor first.
+            if (!ann.interceptor().newInstance().isGridify(ann, arg))
+                return joinPnt.proceed();
+        }
+
+        // Proceed locally for negative threshold parameter.
+        if (ann.threshold() < 0)
+            return joinPnt.proceed();
+
+        // Analyse where to execute method (remotely or locally).
+        if (arg.getInputSize() != UNKNOWN_SIZE && arg.getInputSize() <= ann.threshold())
+            return joinPnt.proceed();
+
+        // Check is split to jobs allowed for input method argument with declared splitSize.
+        checkIsSplitToJobsAllowed(arg, ann);
+
+        try {
+            Ignite ignite = G.ignite(igniteInstanceName);
+
+            return execute(ignite.compute(), joinPnt.getSignature().getDeclaringType(), arg, nodeFilter,
+                ann.threshold(), ann.splitSize(), ann.timeout());
+        }
+        catch (Exception e) {
+            for (Class<?> ex : ((MethodSignature)joinPnt.getSignature()).getMethod().getExceptionTypes()) {
+                // Descend all levels down.
+                Throwable cause = e.getCause();
+
+                while (cause != null) {
+                    if (ex.isAssignableFrom(cause.getClass()))
+                        throw cause;
+
+                    cause = cause.getCause();
+                }
+
+                if (ex.isAssignableFrom(e.getClass()))
+                    throw e;
+            }
+
+            throw new GridifyRuntimeException("Undeclared exception thrown: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/GridifySetToValueAspectJAspect.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/GridifySetToValueAspectJAspect.java
new file mode 100644
index 0000000..55cebe4
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/GridifySetToValueAspectJAspect.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.compute.gridify.aop.aspectj;
+
+import java.lang.reflect.Method;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.compute.gridify.GridifyInterceptor;
+import org.apache.ignite.compute.gridify.GridifyNodeFilter;
+import org.apache.ignite.compute.gridify.GridifyRuntimeException;
+import org.apache.ignite.compute.gridify.GridifySetToValue;
+import org.apache.ignite.compute.gridify.aop.GridifySetToValueAbstractAspect;
+import org.apache.ignite.internal.util.gridify.GridifyArgumentBuilder;
+import org.apache.ignite.internal.util.gridify.GridifyRangeArgument;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.G;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+
+import static org.apache.ignite.IgniteState.STARTED;
+import static org.apache.ignite.internal.util.gridify.GridifyUtils.UNKNOWN_SIZE;
+
+/**
+ * AspectJ aspect that cross-cuts on all methods grid-enabled with
+ * {@link GridifySetToValue} annotation and potentially executes them on
+ * remote node.
+ * <p>
+ * See {@link GridifySetToValue} documentation for more information about execution of
+ * {@code gridified} methods.
+ * @see GridifySetToValue
+ */
+@Aspect
+public class GridifySetToValueAspectJAspect extends GridifySetToValueAbstractAspect {
+    /**
+     * Aspect implementation which executes grid-enabled methods on remote
+     * nodes.
+     *
+     * @param joinPnt Join point provided by AspectJ AOP.
+     * @return Method execution result.
+     * @throws Throwable If execution failed.
+     */
+    @SuppressWarnings({"ProhibitedExceptionDeclared", "ProhibitedExceptionThrown"})
+    @Around("execution(@org.apache.ignite.compute.gridify.GridifySetToValue * *(..)) && " +
+        "!cflow(call(* org.apache.ignite.compute.ComputeJob.*(..)))")
+    public Object gridify(ProceedingJoinPoint joinPnt) throws Throwable {
+        Method mtd = ((MethodSignature)joinPnt.getSignature()).getMethod();
+
+        GridifySetToValue ann = mtd.getAnnotation(GridifySetToValue.class);
+
+        assert ann != null : "Intercepted method does not have gridify annotation.";
+
+        // Since annotations in Java don't allow 'null' as default value
+        // we have accept an empty string and convert it here.
+        // NOTE: there's unintended behavior when user specifies an empty
+        // string as intended Igninte instance name.
+        // NOTE: the 'ann.igniteInstanceName() == null' check is added to mitigate
+        // annotation bugs in some scripting languages (e.g. Groovy).
+        String igniteInstanceName = F.isEmpty(ann.igniteInstanceName()) ? ann.gridName() : ann.igniteInstanceName();
+
+        if (F.isEmpty(igniteInstanceName))
+            igniteInstanceName = null;
+
+        if (G.state(igniteInstanceName) != STARTED)
+            throw new IgniteCheckedException("Grid is not locally started: " + igniteInstanceName);
+
+        GridifyNodeFilter nodeFilter = null;
+
+        if (!ann.nodeFilter().equals(GridifyNodeFilter.class))
+            nodeFilter = ann.nodeFilter().newInstance();
+
+        // Check is method allowed for gridify.
+        checkMethodSignature(mtd);
+
+        GridifyArgumentBuilder argBuilder = new GridifyArgumentBuilder();
+
+        // Creates task argument.
+        GridifyRangeArgument arg = argBuilder.createTaskArgument(
+            mtd.getDeclaringClass(),
+            mtd.getName(),
+            mtd.getReturnType(),
+            mtd.getParameterTypes(),
+            mtd.getParameterAnnotations(),
+            joinPnt.getArgs(),
+            joinPnt.getTarget());
+
+        if (!ann.interceptor().equals(GridifyInterceptor.class)) {
+            // Check interceptor first.
+            if (!ann.interceptor().newInstance().isGridify(ann, arg))
+                return joinPnt.proceed();
+        }
+
+        // Proceed locally for negative threshold parameter.
+        if (ann.threshold() < 0)
+            return joinPnt.proceed();
+
+        // Analyse where to execute method (remotely or locally).
+        if (arg.getInputSize() != UNKNOWN_SIZE && arg.getInputSize() <= ann.threshold())
+            return joinPnt.proceed();
+
+        // Check is split to jobs allowed for input method argument with declared splitSize.
+        checkIsSplitToJobsAllowed(arg, ann);
+
+        try {
+            Ignite ignite = G.ignite(igniteInstanceName);
+
+            return execute(mtd, ignite.compute(), joinPnt.getSignature().getDeclaringType(), arg, nodeFilter,
+                ann.threshold(), ann.splitSize(), ann.timeout());
+        }
+        catch (Exception e) {
+            for (Class<?> ex : ((MethodSignature)joinPnt.getSignature()).getMethod().getExceptionTypes()) {
+                // Descend all levels down.
+                Throwable cause = e.getCause();
+
+                while (cause != null) {
+                    if (ex.isAssignableFrom(cause.getClass()))
+                        throw cause;
+
+                    cause = cause.getCause();
+                }
+
+                if (ex.isAssignableFrom(e.getClass()))
+                    throw e;
+            }
+
+            throw new GridifyRuntimeException("Undeclared exception thrown: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/package-info.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/package-info.java
new file mode 100644
index 0000000..316e60a
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/aspectj/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 description. -->
+ * Contains all classes used by AspectJ AOP implementation.
+ */
+
+package org.apache.ignite.compute.gridify.aop.aspectj;
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySetToSetSpringAspect.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySetToSetSpringAspect.java
new file mode 100644
index 0000000..dba2ac5
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySetToSetSpringAspect.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.compute.gridify.aop.spring;
+
+import java.lang.reflect.Method;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.compute.gridify.GridifyInterceptor;
+import org.apache.ignite.compute.gridify.GridifyNodeFilter;
+import org.apache.ignite.compute.gridify.GridifyRuntimeException;
+import org.apache.ignite.compute.gridify.GridifySetToSet;
+import org.apache.ignite.compute.gridify.aop.GridifySetToSetAbstractAspect;
+import org.apache.ignite.internal.util.gridify.GridifyArgumentBuilder;
+import org.apache.ignite.internal.util.gridify.GridifyRangeArgument;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.G;
+
+import static org.apache.ignite.IgniteState.STARTED;
+import static org.apache.ignite.internal.util.gridify.GridifyUtils.UNKNOWN_SIZE;
+
+/**
+ * Spring aspect that cross-cuts on all methods grid-enabled with
+ * {@link GridifySetToSet} annotation and potentially executes them on
+ * remote node.
+ * <p>
+ * Note that Spring uses proxy-based AOP, so in order to be properly
+ * cross-cut, all methods need to be enhanced with {@link GridifySpringEnhancer}
+ * helper.
+ * <p>
+ * See {@link GridifySetToSet} documentation for more information about execution of
+ * {@code gridified} methods.
+ * @see GridifySetToSet
+ */
+public class GridifySetToSetSpringAspect extends GridifySetToSetAbstractAspect implements MethodInterceptor {
+    /**
+     * Aspect implementation which executes grid-enabled methods on remote
+     * nodes.
+     *
+     * {@inheritDoc}
+     */
+    @SuppressWarnings({"ProhibitedExceptionDeclared", "ProhibitedExceptionThrown"})
+    @Override public Object invoke(MethodInvocation invoc) throws Throwable {
+        Method mtd = invoc.getMethod();
+
+        GridifySetToSet ann = mtd.getAnnotation(GridifySetToSet.class);
+
+        assert ann != null : "Intercepted method does not have gridify annotation.";
+
+        // Since annotations in Java don't allow 'null' as default value
+        // we have accept an empty string and convert it here.
+        // NOTE: there's unintended behavior when user specifies an empty
+        // string as intended Ignite instance name.
+        // NOTE: the 'ann.igniteInstanceName() == null' check is added to mitigate
+        // annotation bugs in some scripting languages (e.g. Groovy).
+        String igniteInstanceName = F.isEmpty(ann.igniteInstanceName()) ? ann.gridName() : ann.igniteInstanceName();
+
+        if (F.isEmpty(igniteInstanceName))
+            igniteInstanceName = null;
+
+        if (G.state(igniteInstanceName) != STARTED)
+            throw new IgniteCheckedException("Grid is not locally started: " + igniteInstanceName);
+
+        GridifyNodeFilter nodeFilter = null;
+
+        if (!ann.nodeFilter().equals(GridifyNodeFilter.class))
+            nodeFilter = ann.nodeFilter().newInstance();
+
+        GridifyArgumentBuilder argBuilder = new GridifyArgumentBuilder();
+
+        // Creates task argument.
+        GridifyRangeArgument arg = argBuilder.createTaskArgument(
+            mtd.getDeclaringClass(),
+            mtd.getName(),
+            mtd.getReturnType(),
+            mtd.getParameterTypes(),
+            mtd.getParameterAnnotations(),
+            invoc.getArguments(),
+            invoc.getThis());
+
+        if (!ann.interceptor().equals(GridifyInterceptor.class)) {
+            // Check interceptor first.
+            if (!ann.interceptor().newInstance().isGridify(ann, arg))
+                return invoc.proceed();
+        }
+
+        // Proceed locally for negative threshold parameter.
+        if (ann.threshold() < 0)
+            return invoc.proceed();
+
+        // Analyse where to execute method (remotely or locally).
+        if (arg.getInputSize() != UNKNOWN_SIZE && arg.getInputSize() <= ann.threshold())
+            return invoc.proceed();
+
+        // Check is split to jobs allowed for input method argument with declared splitSize.
+        checkIsSplitToJobsAllowed(arg, ann);
+
+        try {
+            Ignite ignite = G.ignite(igniteInstanceName);
+
+            return execute(ignite.compute(), invoc.getMethod().getDeclaringClass(), arg, nodeFilter,
+                ann.threshold(), ann.splitSize(), ann.timeout());
+        }
+        catch (Exception e) {
+            for (Class<?> ex : invoc.getMethod().getExceptionTypes()) {
+                // Descend all levels down.
+                Throwable cause = e.getCause();
+
+                while (cause != null) {
+                    if (ex.isAssignableFrom(cause.getClass()))
+                        throw cause;
+
+                    cause = cause.getCause();
+                }
+
+                if (ex.isAssignableFrom(e.getClass()))
+                    throw e;
+            }
+
+            throw new GridifyRuntimeException("Undeclared exception thrown: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySetToValueSpringAspect.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySetToValueSpringAspect.java
new file mode 100644
index 0000000..ac5134a
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySetToValueSpringAspect.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.compute.gridify.aop.spring;
+
+import java.lang.reflect.Method;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.compute.gridify.GridifyInterceptor;
+import org.apache.ignite.compute.gridify.GridifyNodeFilter;
+import org.apache.ignite.compute.gridify.GridifyRuntimeException;
+import org.apache.ignite.compute.gridify.GridifySetToValue;
+import org.apache.ignite.compute.gridify.aop.GridifySetToValueAbstractAspect;
+import org.apache.ignite.internal.util.gridify.GridifyArgumentBuilder;
+import org.apache.ignite.internal.util.gridify.GridifyRangeArgument;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.G;
+
+import static org.apache.ignite.IgniteState.STARTED;
+import static org.apache.ignite.internal.util.gridify.GridifyUtils.UNKNOWN_SIZE;
+
+/**
+ * Spring aspect that cross-cuts on all methods grid-enabled with
+ * {@link GridifySetToValue} annotation and potentially executes them on
+ * remote node.
+ * <p>
+ * Note that Spring uses proxy-based AOP, so in order to be properly
+ * cross-cut, all methods need to be enhanced with {@link GridifySpringEnhancer}
+ * helper.
+ * <p>
+ * See {@link GridifySetToValue} documentation for more information about execution of
+ * {@code gridified} methods.
+ * @see GridifySetToValue
+ */
+public class GridifySetToValueSpringAspect extends GridifySetToValueAbstractAspect implements MethodInterceptor {
+    /**
+     * Aspect implementation which executes grid-enabled methods on remote
+     * nodes.
+     *
+     * {@inheritDoc}
+     */
+    @SuppressWarnings({"ProhibitedExceptionDeclared", "ProhibitedExceptionThrown"})
+    @Override public Object invoke(MethodInvocation invoc) throws Throwable {
+        Method mtd = invoc.getMethod();
+
+        GridifySetToValue ann = mtd.getAnnotation(GridifySetToValue.class);
+
+        assert ann != null : "Intercepted method does not have gridify annotation.";
+
+        // Since annotations in Java don't allow 'null' as default value
+        // we have accept an empty string and convert it here.
+        // NOTE: there's unintended behavior when user specifies an empty
+        // string as intended Ignite instance name.
+        // NOTE: the 'ann.igniteInstanceName() == null' check is added to mitigate
+        // annotation bugs in some scripting languages (e.g. Groovy).
+        String igniteInstanceName = F.isEmpty(ann.igniteInstanceName()) ? ann.gridName() : ann.igniteInstanceName();
+
+        if (F.isEmpty(igniteInstanceName))
+            igniteInstanceName = null;
+
+        if (G.state(igniteInstanceName) != STARTED)
+            throw new IgniteCheckedException("Grid is not locally started: " + igniteInstanceName);
+
+        GridifyNodeFilter nodeFilter = null;
+
+        if (!ann.nodeFilter().equals(GridifyNodeFilter.class))
+            nodeFilter = ann.nodeFilter().newInstance();
+
+        GridifyArgumentBuilder argBuilder = new GridifyArgumentBuilder();
+
+        // Creates task argument.
+        GridifyRangeArgument arg = argBuilder.createTaskArgument(
+            mtd.getDeclaringClass(),
+            mtd.getName(),
+            mtd.getReturnType(),
+            mtd.getParameterTypes(),
+            mtd.getParameterAnnotations(),
+            invoc.getArguments(),
+            invoc.getThis());
+
+        if (!ann.interceptor().equals(GridifyInterceptor.class)) {
+            // Check interceptor first.
+            if (!ann.interceptor().newInstance().isGridify(ann, arg))
+                return invoc.proceed();
+        }
+
+        // Proceed locally for negative threshold parameter.
+        if (ann.threshold() < 0)
+            return invoc.proceed();
+
+        // Analyse where to execute method (remotely or locally).
+        if (arg.getInputSize() != UNKNOWN_SIZE && arg.getInputSize() <= ann.threshold())
+            return invoc.proceed();
+
+        // Check is split to jobs allowed for input method argument with declared splitSize.
+        checkIsSplitToJobsAllowed(arg, ann);
+
+        try {
+            Ignite ignite = G.ignite(igniteInstanceName);
+
+            return execute(mtd, ignite.compute(), invoc.getMethod().getDeclaringClass(), arg, nodeFilter,
+                ann.threshold(), ann.splitSize(), ann.timeout());
+        }
+        catch (Exception e) {
+            for (Class<?> ex : invoc.getMethod().getExceptionTypes()) {
+                // Descend all levels down.
+                Throwable cause = e.getCause();
+
+                while (cause != null) {
+                    if (ex.isAssignableFrom(cause.getClass()))
+                        throw cause;
+
+                    cause = cause.getCause();
+                }
+
+                if (ex.isAssignableFrom(e.getClass()))
+                    throw e;
+            }
+
+            throw new GridifyRuntimeException("Undeclared exception thrown: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySpringAspect.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySpringAspect.java
new file mode 100644
index 0000000..6ec8936
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySpringAspect.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.compute.gridify.aop.spring;
+
+import java.lang.reflect.Method;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.compute.gridify.Gridify;
+import org.apache.ignite.compute.gridify.GridifyArgument;
+import org.apache.ignite.compute.gridify.GridifyInterceptor;
+import org.apache.ignite.compute.gridify.GridifyRuntimeException;
+import org.apache.ignite.compute.gridify.aop.GridifyArgumentAdapter;
+import org.apache.ignite.compute.gridify.aop.GridifyDefaultTask;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.G;
+
+import static org.apache.ignite.IgniteState.STARTED;
+
+/**
+ * Spring aspect that cross-cuts on all methods grid-enabled with
+ * {@link org.apache.ignite.compute.gridify.Gridify} annotation and potentially executes them on
+ * remote node.
+ * <p>
+ * Note that Spring uses proxy-based AOP, so in order to be properly
+ * cross-cut, all methods need to be enhanced with {@link GridifySpringEnhancer}
+ * helper.
+ * <p>
+ * See {@link org.apache.ignite.compute.gridify.Gridify} documentation for more information about execution of
+ * {@code gridified} methods.
+ * @see org.apache.ignite.compute.gridify.Gridify
+ */
+public class GridifySpringAspect implements MethodInterceptor {
+    /**
+     * Aspect implementation which executes grid-enabled methods on remote
+     * nodes.
+     *
+     * {@inheritDoc}
+     */
+    @SuppressWarnings({"ProhibitedExceptionDeclared", "ProhibitedExceptionThrown", "unchecked"})
+    @Override public Object invoke(MethodInvocation invoc) throws Throwable {
+        Method mtd = invoc.getMethod();
+
+        Gridify ann = mtd.getAnnotation(Gridify.class);
+
+        assert ann != null : "Intercepted method does not have gridify annotation.";
+
+        // Since annotations in Java don't allow 'null' as default value
+        // we have accept an empty string and convert it here.
+        // NOTE: there's unintended behavior when user specifies an empty
+        // string as intended Ignite instance name.
+        // NOTE: the 'ann.igniteInstanceName() == null' check is added to mitigate
+        // annotation bugs in some scripting languages (e.g. Groovy).
+        String igniteInstanceName = F.isEmpty(ann.igniteInstanceName()) ? ann.gridName() : ann.igniteInstanceName();
+
+        if (F.isEmpty(igniteInstanceName))
+            igniteInstanceName = null;
+
+        if (G.state(igniteInstanceName) != STARTED)
+            throw new IgniteCheckedException("Grid is not locally started: " + igniteInstanceName);
+
+        // Initialize defaults.
+        GridifyArgument arg = new GridifyArgumentAdapter(mtd.getDeclaringClass(), mtd.getName(),
+            mtd.getParameterTypes(), invoc.getArguments(), invoc.getThis());
+
+        if (!ann.interceptor().equals(GridifyInterceptor.class)) {
+            // Check interceptor first.
+            if (!ann.interceptor().newInstance().isGridify(ann, arg))
+                return invoc.proceed();
+        }
+
+        if (!ann.taskClass().equals(GridifyDefaultTask.class) && !ann.taskName().isEmpty())
+            throw new IgniteCheckedException("Gridify annotation must specify either Gridify.taskName() or " +
+                "Gridify.taskClass(), but not both: " + ann);
+
+        try {
+            Ignite ignite = G.ignite(igniteInstanceName);
+
+            if (!ann.taskClass().equals(GridifyDefaultTask.class))
+                return ignite.compute().withTimeout(ann.timeout()).execute(
+                    (Class<? extends ComputeTask<GridifyArgument, Object>>)ann.taskClass(), arg);
+
+            // If task name was not specified.
+            if (ann.taskName().isEmpty())
+                return ignite.compute().withTimeout(ann.timeout()).execute(
+                    new GridifyDefaultTask(invoc.getMethod().getDeclaringClass()), arg);
+
+            // If task name was specified.
+            return ignite.compute().withTimeout(ann.timeout()).execute(ann.taskName(), arg);
+        }
+        catch (Exception e) {
+            for (Class<?> ex : invoc.getMethod().getExceptionTypes()) {
+                // Descend all levels down.
+                Throwable cause = e.getCause();
+
+                while (cause != null) {
+                    if (ex.isAssignableFrom(cause.getClass()))
+                        throw cause;
+
+                    cause = cause.getCause();
+                }
+
+                if (ex.isAssignableFrom(e.getClass()))
+                    throw e;
+            }
+
+            throw new GridifyRuntimeException("Undeclared exception thrown: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySpringEnhancer.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySpringEnhancer.java
new file mode 100644
index 0000000..c174683
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySpringEnhancer.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.compute.gridify.aop.spring;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+
+/**
+ * Spring AOP enhancer. Use it to grid-enable methods annotated with
+ * {@link org.apache.ignite.compute.gridify.Gridify}, {@link org.apache.ignite.compute.gridify.GridifySetToValue} and
+ * {@link org.apache.ignite.compute.gridify.GridifySetToSet} annotations.
+ * <p>
+ * Note, that Spring AOP requires that all grid-enabled methods must
+ * be {@code enhanced} because it is proxy-based. Other AOP implementations,
+ * such as JBoss or AspectJ don't require special handling.
+ * <p>
+ * See {@link org.apache.ignite.compute.gridify.Gridify} documentation for more information about execution of
+ * {@code gridified} methods.
+ * @see org.apache.ignite.compute.gridify.Gridify
+ * @see org.apache.ignite.compute.gridify.GridifySetToValue
+ * @see org.apache.ignite.compute.gridify.GridifySetToSet
+ */
+public final class GridifySpringEnhancer {
+    /** Spring aspect. */
+    private static final GridifySpringAspect dfltAsp = new GridifySpringAspect();
+
+    /** Spring aspect. */
+    private static final GridifySetToSetSpringAspect setToSetAsp = new GridifySetToSetSpringAspect();
+
+    /** Spring aspect. */
+    private static final GridifySetToValueSpringAspect setToValAsp = new GridifySetToValueSpringAspect();
+
+    /**
+     * Enforces singleton.
+     */
+    private GridifySpringEnhancer() {
+        // No-op.
+    }
+
+    /**
+     * Enhances the object on load.
+     *
+     * @param <T> Type of the object to enhance.
+     * @param obj Object to augment/enhance.
+     * @return Enhanced object.
+     */
+    @SuppressWarnings({"unchecked"})
+    public static <T> T enhance(T obj) {
+        ProxyFactory proxyFac = new ProxyFactory(obj);
+
+        proxyFac.addAdvice(dfltAsp);
+        proxyFac.addAdvice(setToValAsp);
+        proxyFac.addAdvice(setToSetAsp);
+
+        while (proxyFac.getAdvisors().length > 0)
+            proxyFac.removeAdvisor(0);
+
+        proxyFac.addAdvisor(new DefaultPointcutAdvisor(
+            new GridifySpringPointcut(GridifySpringPointcut.GridifySpringPointcutType.DFLT), dfltAsp));
+        proxyFac.addAdvisor(new DefaultPointcutAdvisor(
+            new GridifySpringPointcut(GridifySpringPointcut.GridifySpringPointcutType.SET_TO_VALUE), setToValAsp));
+        proxyFac.addAdvisor(new DefaultPointcutAdvisor(
+            new GridifySpringPointcut(GridifySpringPointcut.GridifySpringPointcutType.SET_TO_SET), setToSetAsp));
+
+        return (T)proxyFac.getProxy();
+    }
+}
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySpringPointcut.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySpringPointcut.java
new file mode 100644
index 0000000..43b26b6
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/GridifySpringPointcut.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.compute.gridify.aop.spring;
+
+import java.lang.reflect.Method;
+import org.apache.ignite.compute.gridify.Gridify;
+import org.apache.ignite.compute.gridify.GridifySetToSet;
+import org.apache.ignite.compute.gridify.GridifySetToValue;
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.MethodMatcher;
+import org.springframework.aop.Pointcut;
+
+/**
+ * Pointcut used by gridified aspects to find methods
+ * annotated with {@link org.apache.ignite.compute.gridify.Gridify}, {@link GridifySetToValue} and
+ * {@link GridifySetToSet} annotations.
+ */
+public class GridifySpringPointcut implements Pointcut {
+    /**
+     * Class filter.
+     */
+    private static final ClassFilter filter = new ClassFilter() {
+        @SuppressWarnings({"RawUseOfParameterizedType"})
+        @Override public boolean matches(Class cls) {
+            return true;
+        }
+    };
+
+    /** Method matcher. */
+    private static final MethodMatcher dfltMatcher = new GridifyMethodMatcher() {
+        // Warning suppression is due to Spring...
+        @Override public boolean matches(Method method, Class cls) {
+            return cls.isAnnotationPresent(Gridify.class) || method.isAnnotationPresent(Gridify.class);
+        }
+    };
+
+    /** Method matcher. */
+    private static final MethodMatcher setToValueMatcher = new GridifyMethodMatcher() {
+        // Warning suppression is due to Spring...
+        @Override public boolean matches(Method method, Class cls) {
+            return cls.isAnnotationPresent(GridifySetToValue.class) || method.isAnnotationPresent(GridifySetToValue.class);
+        }
+    };
+
+    /** Method matcher. */
+    private static final MethodMatcher setToSetMatcher = new GridifyMethodMatcher() {
+        // Warning suppression is due to Spring...
+        @Override public boolean matches(Method method, Class cls) {
+            return cls.isAnnotationPresent(GridifySetToSet.class) || method.isAnnotationPresent(GridifySetToSet.class);
+        }
+    };
+
+    /** */
+    private final GridifySpringPointcutType type;
+
+    /**
+     * Creates pointcut associated with specific aspect.
+     *
+     * @param type Type.
+     */
+    public GridifySpringPointcut(GridifySpringPointcutType type) {
+        assert type != null;
+
+        this.type = type;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClassFilter getClassFilter() {
+        return filter;
+    }
+
+    /** {@inheritDoc} */
+    @Override public MethodMatcher getMethodMatcher() {
+        switch (type) {
+            case DFLT: return dfltMatcher;
+            case SET_TO_VALUE: return setToValueMatcher;
+            case SET_TO_SET: return setToSetMatcher;
+
+            default:
+                assert false : "Unknown pointcut type: " + type;
+        }
+
+        return null;
+    }
+
+    /**
+     * Method matcher.
+     */
+    private abstract static class GridifyMethodMatcher implements MethodMatcher {
+        /** {@inheritDoc} */
+        @Override public abstract boolean matches(Method method, Class cls);
+
+        /** {@inheritDoc} */
+        @Override public boolean isRuntime() {
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        // Warning suppression is due to Spring...
+        @SuppressWarnings({"RawUseOfParameterizedType"})
+        @Override public boolean matches(Method method, Class aClass, Object[] objs) {
+            // No-op.
+            return false;
+        }
+    }
+
+    /**
+     * Pointcut type.
+     */
+    @SuppressWarnings({"PublicInnerClass"})
+    public enum GridifySpringPointcutType {
+        /** */
+        DFLT,
+
+        /** */
+        SET_TO_VALUE,
+
+        /** */
+        SET_TO_SET
+    }
+}
diff --git a/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/package-info.java b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/package-info.java
new file mode 100644
index 0000000..35ac92c
--- /dev/null
+++ b/modules/aop-ext/src/main/java/org/apache/ignite/compute/gridify/aop/spring/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 description. -->
+ * Contains all classes used by Spring AOP implementation.
+ */
+
+package org.apache.ignite.compute.gridify.aop.spring;
diff --git a/modules/aop-ext/src/test/config/aop/aspectj/META-INF/aop.xml b/modules/aop-ext/src/test/config/aop/aspectj/META-INF/aop.xml
new file mode 100644
index 0000000..f80c4a5
--- /dev/null
+++ b/modules/aop-ext/src/test/config/aop/aspectj/META-INF/aop.xml
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<!DOCTYPE aspectj PUBLIC
+    "-//AspectJ//DTD 1.5.0//EN"
+    "http://www.eclipse.org/aspectj/dtd/aspectj_1_5_0.dtd">
+
+<aspectj>
+    <weaver options="-Xset:weaveJavaPackages=true,weaveJavaxPackages=true -Xreweavable">
+        <!-- BEA libs. -->
+        <exclude within="weblogic..*"/>
+        <exclude within="com.bea..*"/>
+        <exclude within="bea..*"/>
+        <exclude within="com.adventnet..*"/>
+        <exclude within="com.asn1c..*"/>
+        <exclude within="com.beasys..*"/>
+        <exclude within="com.bluecast..*"/>
+        <exclude within="com.certicom..*"/>
+        <exclude within="com.netscape..*"/>
+        <exclude within="com.octetstring..*"/>
+        <exclude within="com.oroinc..*"/>
+        <exclude within="com.rsa..*"/>
+        <exclude within="com.ziclix..*"/>
+        <exclude within="kodo.jdbc..*"/>
+        <exclude within="jxxload_help..*"/>
+        <exclude within="netscape..*"/>
+        <exclude within="org.mozilla..*"/>
+        <exclude within="org.python..*"/>
+
+        <!-- WebSphere (IBM) libs. -->
+        <exclude within="com.ibm..*"/>
+
+        <!-- Spring libs. -->
+        <exclude within="org.springframework..*"/>
+        <exclude within="org.aopalliance..*"/>
+
+        <!-- SUN libs. -->
+        <exclude within="com.sun..*"/>
+        <exclude within="sun..*"/>
+        <exclude within="com.iplanet..*"/>
+        <exclude within="org.jcp..*"/>
+        <exclude within="org.omg..*"/>
+        <exclude within="org.omg..*"/>
+
+        <!-- Oracle. -->
+        <exclude within="oracle..*"/>
+
+        <!-- Hibernate libs. -->
+        <exclude within="org.hibernate..*"/>
+
+        <!-- JBoss libs. -->
+        <exclude within="org.jboss..*"/>
+
+        <!-- JXInsight (tracing) libs. -->
+        <exclude within="com.jinspired..*"/>
+
+        <!-- Tangosol libs. -->
+        <exclude within="com.tangosol..*"/>
+
+        <!-- Apache libs. -->
+        <!--<exclude within="org.apache..*"/>-->
+
+        <!-- Javassist libs. -->
+        <exclude within="javassist..*"/>
+
+        <!-- W3C libs. -->
+        <exclude within="org.w3c..*"/>
+
+        <!-- JNP libs. -->
+        <exclude within="org.jnp..*"/>
+
+        <!-- Hyperic libs. -->
+        <exclude within="org.hyperic..*"/>
+
+        <!-- Scala libs. -->
+        <exclude within="scala..*"/>
+
+        <!-- Visor Scala classes.-->
+        <exclude within="org.apache.ignite.visor..*"/>
+
+        <!-- Enterprise DT FTP libs. -->
+        <exclude within="com.enterprisedt..*"/>
+
+        <!-- Apache Oro lib. -->
+        <exclude within="org.apache.oro..*"/>
+
+        <!-- SLF4J libs. -->
+        <exclude within="org.slf4j..*"/>
+
+        <!-- JSON Lib libs. -->
+        <exclude within="net.sf.json..*"/>
+
+        <!-- EZMorph libs. -->
+        <exclude within="net.sf.ezmorph..*"/>
+
+        <!-- Jetty libs. -->
+        <exclude within="org.eclipse.jetty..*"/>
+
+        <!-- H2 Database Engine libs. -->
+        <exclude within="org.h2..*"/>
+
+        <!-- Cron4J libs. -->
+        <exclude within="it.sauronsoftware.cron4j..*"/>
+
+        <!-- Amazon libs. -->
+        <exclude within="com.amazon..*"/>
+        <exclude within="com.amazonaws..*"/>
+
+        <!-- ANTLR libs. -->
+        <exclude within="antlr..*"/>
+
+        <!-- CGLib. -->
+        <exclude within="net.sf.cglib..*"/>
+
+        <!-- Concurrent libs. -->
+        <exclude within="EDU.oswego..*"/>
+
+        <!-- DOM4J libs. -->
+        <exclude within="org.dom4j..*"/>
+
+        <!-- Google libs. -->
+        <exclude within="com.google..*"/>
+
+        <!-- Jackson libs. -->
+        <exclude within="com.fasterxml.jackson.core..*"/>
+
+        <!-- JLine libs. -->
+        <exclude within="org.fusesource..*"/>
+
+        <!-- Joda libs. -->
+        <exclude within="org.joda..*"/>
+
+        <!-- JSCH libs. -->
+        <exclude within="com.jcraft.jsch..*"/>
+
+        <!-- SnapTree libs. -->
+        <exclude within="edu.stanford..*"/>
+
+        <!-- MemCache libs. -->
+        <exclude within="net.spy..*"/>
+
+        <!-- Trove libs. -->
+        <exclude within="gnu.trove..*"/>
+    </weaver>
+
+    <aspects>
+        <!-- Declare @Gridify aspect to the weaver. -->
+        <aspect name="org.apache.ignite.compute.gridify.aop.aspectj.GridifyAspectJAspect"/>
+        <aspect name="org.apache.ignite.compute.gridify.aop.aspectj.GridifySetToValueAspectJAspect"/>
+        <aspect name="org.apache.ignite.compute.gridify.aop.aspectj.GridifySetToSetAspectJAspect"/>
+
+        <!-- Declare folder to search for aspects. -->
+        <include within="org.apache.ignite.compute.gridify.aop.aspectj.*"/>
+
+        <!-- BEA libs. -->
+        <exclude within="weblogic..*"/>
+        <exclude within="com.bea..*"/>
+        <exclude within="bea..*"/>
+        <exclude within="com.adventnet..*"/>
+        <exclude within="com.asn1c..*"/>
+        <exclude within="com.beasys..*"/>
+        <exclude within="com.bluecast..*"/>
+        <exclude within="com.certicom..*"/>
+        <exclude within="com.netscape..*"/>
+        <exclude within="com.octetstring..*"/>
+        <exclude within="com.oroinc..*"/>
+        <exclude within="com.rsa..*"/>
+        <exclude within="com.ziclix..*"/>
+        <exclude within="kodo.jdbc..*"/>
+        <exclude within="jxxload_help..*"/>
+        <exclude within="netscape..*"/>
+        <exclude within="org.mozilla..*"/>
+        <exclude within="org.python..*"/>
+
+        <!-- WebSphere (IBM) libs. -->
+        <exclude within="com.ibm..*"/>
+
+        <!-- Spring libs. -->
+        <exclude within="org.springframework..*"/>
+        <exclude within="org.aopalliance..*"/>
+
+        <!-- SUN libs. -->
+        <exclude within="com.sun..*"/>
+        <exclude within="sun..*"/>
+        <exclude within="com.iplanet..*"/>
+        <exclude within="org.jcp..*"/>
+        <exclude within="org.omg..*"/>
+        <exclude within="org.omg..*"/>
+
+        <!-- Oracle. -->
+        <exclude within="oracle..*"/>
+
+        <!-- Hibernate libs. -->
+        <exclude within="org.hibernate..*"/>
+
+        <!-- JBoss libs. -->
+        <exclude within="org.jboss..*"/>
+
+        <!-- JXInsight (tracing) libs. -->
+        <exclude within="com.jinspired..*"/>
+
+        <!-- Tangosol libs. -->
+        <exclude within="com.tangosol..*"/>
+
+        <!-- Apache libs. -->
+        <!--<exclude within="org.apache..*"/>-->
+
+        <!-- Javassist libs. -->
+        <exclude within="javassist..*"/>
+
+        <!-- W3C libs. -->
+        <exclude within="org.w3c..*"/>
+
+        <!-- JNP libs. -->
+        <exclude within="org.jnp..*"/>
+
+        <!-- Hyperic libs. -->
+        <exclude within="org.hyperic..*"/>
+
+        <!-- Scala libs. -->
+        <exclude within="scala..*"/>
+
+        <!-- Visor Scala classes.-->
+        <exclude within="org.apache.ignite.visor..*"/>
+
+        <!-- Enterprise DT FTP libs. -->
+        <exclude within="com.enterprisedt..*"/>
+
+        <!-- Apache Oro lib. -->
+        <exclude within="org.apache.oro..*"/>
+
+        <!-- SLF4J libs. -->
+        <exclude within="org.slf4j..*"/>
+
+        <!-- JSON Lib libs. -->
+        <exclude within="net.sf.json..*"/>
+
+        <!-- EZMorph libs. -->
+        <exclude within="net.sf.ezmorph..*"/>
+
+        <!-- Jetty libs. -->
+        <exclude within="org.eclipse.jetty..*"/>
+
+        <!-- H2 Database Engine libs. -->
+        <exclude within="org.h2..*"/>
+
+        <!-- Cron4J libs. -->
+        <exclude within="it.sauronsoftware.cron4j..*"/>
+
+        <!-- Amazon libs. -->
+        <exclude within="com.amazon..*"/>
+        <exclude within="com.amazonaws..*"/>
+
+        <!-- ANTLR libs. -->
+        <exclude within="antlr..*"/>
+
+        <!-- CGLib. -->
+        <exclude within="net.sf.cglib..*"/>
+
+        <!-- Concurrent libs. -->
+        <exclude within="EDU.oswego..*"/>
+
+        <!-- DOM4J libs. -->
+        <exclude within="org.dom4j..*"/>
+
+        <!-- Google libs. -->
+        <exclude within="com.google..*"/>
+
+        <!-- Jackson libs. -->
+        <exclude within="com.fasterxml.jackson.core..*"/>
+
+        <!-- JLine libs. -->
+        <exclude within="org.fusesource..*"/>
+
+        <!-- Joda libs. -->
+        <exclude within="org.joda..*"/>
+
+        <!-- JSCH libs. -->
+        <exclude within="com.jcraft.jsch..*"/>
+
+        <!-- SnapTree libs. -->
+        <exclude within="edu.stanford..*"/>
+
+        <!-- MemCache libs. -->
+        <exclude within="net.spy..*"/>
+
+        <!-- Trove libs. -->
+        <exclude within="gnu.trove..*"/>
+    </aspects>
+</aspectj>
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/AbstractAopTest.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/AbstractAopTest.java
new file mode 100644
index 0000000..a4772b2
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/AbstractAopTest.java
@@ -0,0 +1,778 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.DeploymentMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.events.Event;
+import org.apache.ignite.events.EventType;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.spi.deployment.local.LocalDeploymentSpi;
+import org.apache.ignite.testframework.GridTestClassLoader;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+import static org.apache.ignite.events.EventType.EVT_CLASS_DEPLOYED;
+import static org.apache.ignite.events.EventType.EVT_TASK_DEPLOYED;
+
+/**
+ * Abstract AOP test.
+ */
+@SuppressWarnings( {"OverlyStrongTypeCast", "ProhibitedExceptionDeclared", "IfMayBeConditional"})
+public abstract class AbstractAopTest extends GridCommonAbstractTest {
+    /** */
+    private DeploymentMode depMode = DeploymentMode.PRIVATE;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setDeploymentSpi(new LocalDeploymentSpi());
+
+        cfg.setMetricsUpdateFrequency(500);
+        cfg.setDeploymentMode(depMode);
+
+        cfg.setIncludeEventTypes(EventType.EVTS_ALL);
+
+        return cfg;
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultPrivate() throws Exception {
+        checkDefault(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultIsolated() throws Exception {
+        checkDefault(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultContinuous() throws Exception {
+        checkDefault(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultShared() throws Exception {
+        checkDefault(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultWithUserClassLoaderPrivate() throws Exception {
+        checkDefaultWithUserClassLoader(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultWithUserClassLoaderIsolated() throws Exception {
+        checkDefaultWithUserClassLoader(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultWithUserClassLoaderContinuous() throws Exception {
+        checkDefaultWithUserClassLoader(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultWithUserClassLoaderShared() throws Exception {
+        checkDefaultWithUserClassLoader(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testSingleDeploymentWithUserClassLoaderPrivate() throws Exception {
+        checkSingleDeploymentWithUserClassLoader(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testSingleDeploymentWithUserClassLoaderIsolated() throws Exception {
+        checkSingleDeploymentWithUserClassLoader(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testSingleDeploymentWithUserClassLoaderContinuous() throws Exception {
+        checkSingleDeploymentWithUserClassLoader(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testSingleDeploymentWithUserClassLoaderShared() throws Exception {
+        checkSingleDeploymentWithUserClassLoader(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceWithUserClassLoaderPrivate() throws Exception {
+        checkDefaultResourceWithUserClassLoader(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceWithUserClassLoaderIsolated() throws Exception {
+        checkDefaultResourceWithUserClassLoader(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceWithUserClassLoaderContinuous() throws Exception {
+        checkDefaultResourceWithUserClassLoader(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceWithUserClassLoaderShared() throws Exception {
+        checkDefaultResourceWithUserClassLoader(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassPrivate() throws Exception {
+        checkNonDefaultClass(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassIsolated() throws Exception {
+        checkNonDefaultClass(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassContinuous() throws Exception {
+        checkNonDefaultClass(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassShared() throws Exception {
+        checkNonDefaultClass(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNamePrivate() throws Exception {
+        checkNonDefaultName(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameIsolated() throws Exception {
+        checkNonDefaultName(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameContinuous() throws Exception {
+        checkNonDefaultName(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameShared() throws Exception {
+        checkNonDefaultName(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultExceptionPrivate() throws Exception {
+        checkDefaultException(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultExceptionIsolated() throws Exception {
+        checkDefaultException(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultExceptionContinuous() throws Exception {
+        checkDefaultException(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultExceptionShared() throws Exception {
+        checkDefaultException(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourcePrivate() throws Exception {
+        checkDefaultResource(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceIsolated() throws Exception {
+        checkDefaultResource(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceContinuous() throws Exception {
+        checkDefaultResource(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceShared() throws Exception {
+        checkDefaultResource(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassResourcePrivate() throws Exception {
+        checkNonDefaultClassResource(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassResourceIsolated() throws Exception {
+        checkNonDefaultClassResource(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassResourceContinuous() throws Exception {
+        checkNonDefaultClassResource(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassResourceShared() throws Exception {
+        checkNonDefaultClassResource(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameResourcePrivate() throws Exception {
+        checkNonDefaultNameResource(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameResourceIsolated() throws Exception {
+        checkNonDefaultNameResource(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameResourceContinuous() throws Exception {
+        checkNonDefaultNameResource(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameResourceShared() throws Exception {
+        checkNonDefaultNameResource(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkDefault(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Default AOP Task in Deployment Mode : " + depMode);
+
+        startGrid();
+
+        try {
+            int res;
+
+            Object targetObj = target();
+
+            if (targetObj instanceof TestAopTarget)
+                res = ((TestAopTarget)targetObj).gridifyDefault("1");
+            else
+                res = ((TestAopTargetInterface)targetObj).gridifyDefault("1");
+
+            assert res == 1 : "Invalid gridifyDefault result: " + res;
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkDefaultWithUserClassLoader(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Default AOP Task  in Deployment Mode : " + depMode);
+
+        startGrid();
+
+        int res;
+
+        try {
+            res = -1;
+
+            Object targetObj = targetWithUserClassLoader();
+
+            Method gridifyMtd = targetObj.getClass().getDeclaredMethod("gridifyDefault", String.class);
+
+            res = (Integer)gridifyMtd.invoke(targetObj, "1");
+
+            if (res != 1)
+                fail("Method gridifyDefault returned wrong value [result=" + res + ", expect=1]");
+        }
+        finally {
+            stopGrid();
+        }
+
+        info("Executed @Gridify method gridifyDefault(1) [result=" + res + ']');
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkSingleDeploymentWithUserClassLoader(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        // Create remote grid to execute test on.
+        Ignite locIgnite = startGrid();
+
+        Ignite rmtIgnite = startGrid(getTestIgniteInstanceName() + "Remote");
+
+        try {
+            AtomicInteger locDepCnt = new AtomicInteger(0);
+            AtomicInteger rmtDepCnt = new AtomicInteger(0);
+
+            locIgnite.events().localListen(new TestEventListener(locDepCnt), EVT_TASK_DEPLOYED, EVT_CLASS_DEPLOYED);
+            rmtIgnite.events().localListen(new TestEventListener(rmtDepCnt), EVT_TASK_DEPLOYED, EVT_CLASS_DEPLOYED);
+
+            assertEquals(2, locIgnite.cluster().forPredicate(F.<ClusterNode>alwaysTrue()).nodes().size());
+
+            Object targetObj = targetWithUserClassLoader();
+
+            Method gridifyMtd = targetObj.getClass().getDeclaredMethod("gridifyDefault", String.class);
+
+            info("First invocation.");
+
+            int res = (Integer)gridifyMtd.invoke(targetObj, "1");
+
+            assert res == 1 : "Method gridifyDefault returned wrong value [result=" + res + ", expected=1]";
+
+            info("Second invocation.");
+
+            res = (Integer)gridifyMtd.invoke(targetObj, "1");
+
+            assert res == 1 : "Method gridifyDefault returned wrong value [result=" + res + ", expected=1]";
+
+            assert locDepCnt.get() == 1 : "Invalid local deployment count [expected=1, got=" + locDepCnt.get() + ']';
+            assert rmtDepCnt.get() == 1 : "Invalid remote deployment count [expected=1, got=" + rmtDepCnt.get() + ']';
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkDefaultResourceWithUserClassLoader(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Default AOP Task.");
+
+        startGrid();
+
+        int res;
+
+        try {
+            res = -1;
+
+            Object targetObj = targetWithUserClassLoader();
+
+            ClassLoader cl = Thread.currentThread().getContextClassLoader();
+
+            // Set context classloader as user class loader.
+            Thread.currentThread().setContextClassLoader(targetObj.getClass().getClassLoader());
+
+            Method gridifyMtd = targetObj.getClass().getDeclaredMethod("gridifyDefaultResource", String.class);
+
+            res = (Integer)gridifyMtd.invoke(targetObj, "2");
+
+            if (res != 2)
+                fail("Method gridifyDefaultResource returned wrong value [result=" + res + ", expect=2]");
+
+            // Set old classloader back.
+            Thread.currentThread().setContextClassLoader(cl);
+        }
+        finally {
+            stopGrid();
+        }
+
+        info("Executed @Gridify method gridifyDefaultResource(2) [result=" + res + ']');
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkNonDefaultClass(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Test AOP Task in Deployment Mode : " + depMode);
+
+        startGrid();
+
+        int res;
+
+        try {
+            res = -1;
+
+            Object targetObj = target();
+
+            if (targetObj instanceof TestAopTarget)
+                res = ((TestAopTarget)targetObj).gridifyNonDefaultClass("1");
+            else
+                res = ((TestAopTargetInterface)targetObj).gridifyNonDefaultClass("1");
+
+            if (res != 10)
+                fail("Method gridifyNonDefault returned wrong value [result=" + res + ", expect=10]");
+        }
+        finally {
+            stopGrid();
+        }
+
+        info("Executed @Gridify method gridifyNonDefaultClass(0) [result=" + res + ']');
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkNonDefaultName(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Test AOP Task in Deployment Mode : " + depMode);
+
+        startGrid();
+
+        int res;
+
+        try {
+            res = -1;
+
+            Object targetObj = target();
+
+            if (targetObj instanceof TestAopTarget)
+                res = ((TestAopTarget)targetObj).gridifyNonDefaultName("2");
+            else
+                res = ((TestAopTargetInterface)targetObj).gridifyNonDefaultName("2");
+
+            if (res != 20)
+                fail("Method gridifyNonDefault returned wrong value [result=" + res + ", expect=2]");
+        }
+        finally {
+            stopGrid();
+        }
+
+        info("Executed @Gridify method gridifyNonDefaultName(2) [result=" + res + ']');
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkDefaultException(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Default AOP Task and exception in Deployment Mode : " + depMode);
+
+        startGrid();
+
+        try {
+            Object targetObj = target();
+
+            boolean isE = false;
+
+            try {
+                if (targetObj instanceof TestAopTarget)
+                    ((TestAopTarget)targetObj).gridifyDefaultException("1");
+                else
+                    ((TestAopTargetInterface)targetObj).gridifyDefaultException("1");
+            }
+            catch (TestGridifyException e) {
+                info("@Gridify method gridifyDefaultException(0) returns exception: " + e);
+
+                isE = true;
+            }
+            catch (Exception e) {
+                e.printStackTrace();
+
+                fail("@Gridify method gridifyDefaultException(0) returns exception [exception" + e
+                    + ", expect=" + TestGridifyException.class.getName() + ']');
+            }
+
+            if (!isE)
+                fail("@Gridify method gridifyDefaultException(0) does not return any exception.");
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkDefaultResource(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Default AOP Task in Deploy Mode : " + depMode);
+
+        startGrid();
+
+        int res;
+
+        try {
+            res = -1;
+
+            Object targetObj = target();
+
+            if (targetObj instanceof TestAopTarget)
+                res = ((TestAopTarget)targetObj).gridifyDefaultResource("1");
+            else
+                res = ((TestAopTargetInterface)targetObj).gridifyDefaultResource("1");
+
+            if (res != 1)
+                fail("Method gridifyDefaultResource returned wrong value [result=" + res + ", expect=1]");
+        }
+        finally {
+            stopGrid();
+        }
+
+        info("Executed @Gridify method gridifyDefaultResource(0) [result=" + res + ']');
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkNonDefaultClassResource(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Test AOP Task in Deploy Mode : " + depMode);
+
+        startGrid();
+
+        int res;
+
+        try {
+            res = -1;
+
+            Object targetObj = target();
+
+            if (targetObj instanceof TestAopTarget)
+                res = ((TestAopTarget)targetObj).gridifyNonDefaultClassResource("3");
+            else
+                res = ((TestAopTargetInterface)targetObj).gridifyNonDefaultClassResource("3");
+
+            if (res != 30)
+                fail("Method gridifyNonDefaultClassResource returned wrong value [result=" + res + ", expect=3]");
+        }
+        finally {
+            stopGrid();
+        }
+
+        info("Executed @Gridify method gridifyNonDefaultClassResource(3) [result=" + res + ']');
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkNonDefaultNameResource(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Test AOP Task in Deployment Mode : " + depMode);
+
+        startGrid();
+
+        int res;
+
+        try {
+            res = -1;
+
+            Object targetObj = target();
+
+            if (targetObj instanceof TestAopTarget)
+                res = ((TestAopTarget)targetObj).gridifyNonDefaultNameResource("4");
+            else
+                res = ((TestAopTargetInterface)targetObj).gridifyNonDefaultNameResource("4");
+
+            if (res != 40)
+                fail("Method gridifyNonDefaultNameResource returned wrong value [result=" + res + ", expect=4]");
+        }
+        finally {
+            stopGrid();
+        }
+
+        info("Executed @Gridify method gridifyNonDefaultNameResource(4) [result=" + res + ']');
+    }
+
+    /**
+     * @return Test target.
+     */
+    protected abstract Object target();
+
+    /**
+     * @return Target.
+     * @throws Exception If failed.
+     */
+    protected Object targetWithUserClassLoader() throws Exception {
+        // Notice that we use another resource naming because file has path.
+        ClassLoader tstClsLdr = new GridTestClassLoader(
+            Collections.singletonMap("org/apache/ignite/gridify/test_resource.properties", "param1=2"),
+            getClass().getClassLoader(),
+            TestAopTarget.class.getName(), TestAopTargetInterface.class.getName());
+
+        return tstClsLdr.loadClass("org.apache.ignite.gridify.TestAopTarget").newInstance();
+    }
+
+    /**
+     * Event listener.
+     */
+    private static final class TestEventListener implements IgnitePredicate<Event> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Counter. */
+        private final AtomicInteger cnt;
+
+        /**
+         * @param cnt Deploy counter.
+         */
+        private TestEventListener(AtomicInteger cnt) {
+            this.cnt = cnt;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean apply(Event evt) {
+            if ((evt.type() == EVT_TASK_DEPLOYED || evt.type() == EVT_CLASS_DEPLOYED) &&
+                evt.message() != null && evt.message().contains("TestAopTarget"))
+                cnt.addAndGet(1);
+
+            return true;
+        }
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/BasicAopSelfTest.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/BasicAopSelfTest.java
new file mode 100644
index 0000000..cee043e
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/BasicAopSelfTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.compute.gridify.Gridify;
+import org.apache.ignite.compute.gridify.GridifyArgument;
+import org.apache.ignite.compute.gridify.GridifyTaskSplitAdapter;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+/**
+ * Tries to execute dummy gridified task. It should fail because grid is not started.
+ * <p>
+ * The main purpose of this test is to check that AOP is properly configured. It should
+ * be included in all suites that require AOP.
+ */
+public class BasicAopSelfTest extends GridCommonAbstractTest {
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testAop() throws Exception {
+        try {
+            gridify();
+
+            fail();
+        }
+        catch (Exception e) {
+            // No-op.
+        }
+    }
+
+    /**
+     * Gridified method.
+     */
+    @Gridify(taskClass = TestTask.class)
+    private void gridify() {
+        // No-op
+    }
+
+    /**
+     * Test task.
+     */
+    private static class TestTask extends GridifyTaskSplitAdapter<Void> {
+        /** {@inheritDoc} */
+        @Override protected Collection<? extends ComputeJob> split(int gridSize,
+            GridifyArgument arg) {
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Void reduce(List<ComputeJobResult> results) {
+            return null;
+        }
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToSetTarget.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToSetTarget.java
new file mode 100644
index 0000000..593cd65
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToSetTarget.java
@@ -0,0 +1,378 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.compute.gridify.GridifySetToSet;
+
+/**
+ * Test set-to-set target.
+ */
+public class GridifySetToSetTarget implements GridifySetToSetTargetInterface, Serializable {
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    @Override public Collection<Long> findPrimes(Collection<Long> input) {
+        return findPrimes0(input);
+    }
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2)
+    @Override public Collection<Long> findPrimesWithoutSplitSize(Collection<Long> input) {
+        return findPrimes0(input);
+    }
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget")
+    @Override public Collection<Long> findPrimesWithoutSplitSizeAndThreshold(Collection<Long> input) {
+        return findPrimes0(input);
+    }
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget")
+    @Override public Collection<Long> findPrimesInListWithoutSplitSizeAndThreshold(List<Long> input) {
+        return findPrimes0(input);
+    }
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @SuppressWarnings({"CollectionDeclaredAsConcreteClass"})
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget")
+    @Override public Collection<Long> findPrimesInArrayListWithoutSplitSizeAndThreshold(ArrayList<Long> input) {
+        return findPrimes0(input);
+    }
+
+    /**
+     * Find prime numbers in array.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    @Override public Long[] findPrimesInArray(Long[] input) {
+        return findPrimesInArray0(input);
+    }
+
+    /**
+     * Find prime numbers in primitive array.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    @Override public long[] findPrimesInPrimitiveArray(long[] input) {
+        return findPrimesInPrimitiveArray0(input);
+    }
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    private Collection<Long> findPrimes0(Iterable<Long> input) {
+        System.out.println(">>>");
+        System.out.println("Find primes in: " + input);
+        System.out.println(">>>");
+
+        Collection<Long> res = new ArrayList<>();
+
+        for (Long val : input) {
+            Long divisor = checkPrime(val, 2, val);
+
+            if (divisor == null)
+                res.add(val);
+        }
+
+        return res;
+    }
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    private Long[] findPrimesInArray0(Long[] input) {
+        System.out.println(">>>");
+        System.out.println("Find primes in array: " + Arrays.asList(input));
+        System.out.println(">>>");
+
+        Collection<Long> res = new ArrayList<>();
+
+        for (Long val : input) {
+            Long divisor = checkPrime(val, 2, val);
+
+            if (divisor == null)
+                res.add(val);
+        }
+
+        return res.toArray(new Long[res.size()]);
+    }
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    private long[] findPrimesInPrimitiveArray0(long[] input) {
+        System.out.println(">>>");
+        System.out.println("Find primes in primitive array: " + Arrays.toString(input));
+        System.out.println(">>>");
+
+        Collection<Long> res = new ArrayList<>();
+
+        for (Long val : input) {
+            Long divisor = checkPrime(val, 2, val);
+
+            if (divisor == null)
+                res.add(val);
+        }
+
+        long[] arr = new long[res.size()];
+
+        int i = 0;
+
+        for (Long element : res) {
+            arr[i] = element;
+            i++;
+        }
+
+        return arr;
+    }
+
+    /**
+     * Find prime numbers in iterator.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    @Override public Iterator<Long> findPrimesWithIterator(Iterator<Long> input) {
+        System.out.println(">>>");
+        System.out.println("Find primes in iterator: " + input);
+        System.out.println(">>>");
+
+        Collection<Long> res = new ArrayList<>();
+
+        while (input.hasNext()) {
+            Long val = input.next();
+
+            Long divisor = checkPrime(val, 2, val);
+
+            if (divisor == null)
+                res.add(val);
+        }
+
+        return new MathIteratorAdapter<>(res);
+    }
+
+    /**
+     * Find prime numbers in enumeration.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    @Override public Enumeration<Long> findPrimesWithEnumeration(Enumeration<Long> input) {
+        System.out.println(">>>");
+        System.out.println("Find primes in enumeration: " + input);
+        System.out.println(">>>");
+
+        Collection<Long> res = new ArrayList<>();
+
+        while (input.hasMoreElements()) {
+            Long val = input.nextElement();
+
+            Long divisor = checkPrime(val, 2, val);
+
+            if (divisor == null)
+                res.add(val);
+        }
+
+        return new MathEnumerationAdapter<>(res);
+    }
+
+    /**
+     * Method to check value for prime.
+     * Returns first divisor found or {@code null} if no divisor was found.
+     *
+     * @param val Value to check for prime.
+     * @param minRage Lower boundary of divisors range.
+     * @param maxRange Upper boundary of divisors range.
+     * @return First divisor found or {@code null} if no divisor was found.
+     */
+    private Long checkPrime(long val, long minRage, long maxRange) {
+        // Loop through all divisors in the range and check if the value passed
+        // in is divisible by any of these divisors.
+        // Note that we also check for thread interruption which may happen
+        // if the job was cancelled from the grid task.
+        for (long divisor = minRage; divisor <= maxRange && !Thread.currentThread().isInterrupted(); divisor++) {
+            if (divisor != 1 && divisor != val && val % divisor == 0)
+                return divisor;
+        }
+
+        return null;
+    }
+
+    /**
+     * Serializable {@link Enumeration} implementation based on {@link Collection}.
+     */
+    private static class MathEnumerationAdapter<T> implements Enumeration<T>, Serializable {
+        /** */
+        private Collection<T> col;
+
+        /** */
+        private transient Iterator<T> iter;
+
+        /**
+         * Creates enumeration.
+         *
+         * @param col Collection.
+         */
+        private MathEnumerationAdapter(Collection<T> col) {
+            this.col = col;
+
+            iter = col.iterator();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean hasMoreElements() {
+            return iter.hasNext();
+        }
+
+        /** {@inheritDoc} */
+        @Override public T nextElement() {
+            return iter.next();
+        }
+
+        /**
+         * Recreate inner state for object after deserialization.
+         *
+         * @param in Input stream.
+         * @throws ClassNotFoundException Thrown in case of error.
+         * @throws IOException Thrown in case of error.
+         */
+        private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
+            // Always perform the default de-serialization first.
+            in.defaultReadObject();
+
+            iter = col.iterator();
+        }
+
+        /**
+         * @param out Output stream
+         * @throws IOException Thrown in case of error.
+         */
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            // Perform the default serialization for all non-transient, non-static fields.
+            out.defaultWriteObject();
+        }
+    }
+
+    /**
+     * Serializable {@link Iterator} implementation based on {@link Collection}.
+     */
+    private static class MathIteratorAdapter<T> implements Iterator<T>, Serializable {
+        /** */
+        private Collection<T> col;
+
+        /** */
+        private transient Iterator<T> iter;
+
+        /**
+         * @param col Collection.
+         */
+        MathIteratorAdapter(Collection<T> col) {
+            this.col = col;
+
+            iter = col.iterator();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean hasNext() {
+            return iter.hasNext();
+        }
+
+        /** {@inheritDoc} */
+        @Override public T next() {
+            return iter.next();
+        }
+
+        /** {@inheritDoc} */
+        @Override public void remove() {
+            iter.remove();
+        }
+
+        /**
+         * Recreate inner state for object after deserialization.
+         *
+         * @param in Input stream.
+         * @throws ClassNotFoundException Thrown in case of error.
+         * @throws IOException Thrown in case of error.
+         */
+        private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
+            // Always perform the default de-serialization first.
+            in.defaultReadObject();
+
+            iter = col.iterator();
+        }
+
+        /**
+         * @param out Output stream
+         * @throws IOException Thrown in case of error.
+         */
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            // Perform the default serialization for all non-transient, non-static fields.
+            out.defaultWriteObject();
+        }
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToSetTargetInterface.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToSetTargetInterface.java
new file mode 100644
index 0000000..4a51eda
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToSetTargetInterface.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.compute.gridify.GridifySetToSet;
+
+/**
+ * Test set-to-set target interface.
+ */
+public interface GridifySetToSetTargetInterface {
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    public Collection<Long> findPrimes(Collection<Long> input);
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2)
+    public Collection<Long> findPrimesWithoutSplitSize(Collection<Long> input);
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget")
+    public Collection<Long> findPrimesWithoutSplitSizeAndThreshold(Collection<Long> input);
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget")
+    public Collection<Long> findPrimesInListWithoutSplitSizeAndThreshold(List<Long> input);
+
+    /**
+     * Find prime numbers in collection.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @SuppressWarnings({"CollectionDeclaredAsConcreteClass"})
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget")
+    public Collection<Long> findPrimesInArrayListWithoutSplitSizeAndThreshold(ArrayList<Long> input);
+
+    /**
+     * Find prime numbers in array.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    public Long[] findPrimesInArray(Long[] input);
+
+    /**
+     * Find prime numbers in primitive array.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    public long[] findPrimesInPrimitiveArray(long[] input);
+
+    /**
+     * Find prime numbers in iterator.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    public Iterator<Long> findPrimesWithIterator(Iterator<Long> input);
+
+    /**
+     * Find prime numbers in enumeration.
+     *
+     * @param input Input collection.
+     * @return Prime numbers.
+     */
+    @GridifySetToSet(igniteInstanceName = "GridifySetToSetTarget", threshold = 2, splitSize = 2)
+    public Enumeration<Long> findPrimesWithEnumeration(Enumeration<Long> input);
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToValueTarget.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToValueTarget.java
new file mode 100644
index 0000000..847b762
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToValueTarget.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.compute.gridify.GridifySetToValue;
+
+/**
+ * Test set-to-value target.
+ */
+public class GridifySetToValueTarget implements GridifySetToValueTargetInterface, Serializable {
+    /**
+     * Find maximum value in collection.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    @Override public Long findMaximum(Collection<Long> input) {
+        return findMaximum0(input);
+    }
+
+    /**
+     * Find maximum value in collection.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget")
+    @Override public Long findMaximumInList(List<Long> input) {
+        return findMaximum0(input);
+    }
+
+    /**
+     * Find maximum value in collection.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2)
+    @Override public Long findMaximumWithoutSplitSize(Collection<Long> input) {
+        return findMaximum0(input);
+    }
+
+    /**
+     * Find maximum value in collection.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget")
+    @Override public Long findMaximumWithoutSplitSizeAndThreshold(Collection<Long> input) {
+        return findMaximum0(input);
+    }
+
+    /**
+     * Find maximum in array.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    @Override public Long findPrimesInArray(Long[] input) {
+        return findMaximumInArray0(input);
+    }
+
+    /**
+     * Find maximum in primitive array.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    @Override public long findMaximumInPrimitiveArray(long[] input) {
+        return findMaximumInPrimitiveArray0(input);
+    }
+
+    /**
+     * Find maximum value in collection.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    private Long findMaximum0(Collection<Long> input) {
+        System.out.println(">>>");
+        System.out.println("Find maximum in: " + input);
+        System.out.println(">>>");
+
+        return Collections.max(input);
+    }
+
+    /**
+     * Find maximum value in array.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    private Long findMaximumInArray0(Long[] input) {
+        System.out.println(">>>");
+        System.out.println("Find maximum in array: " + Arrays.asList(input));
+        System.out.println(">>>");
+
+        return Collections.max(Arrays.asList(input));
+    }
+
+    /**
+     * Find maximum value in array.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    private long findMaximumInPrimitiveArray0(long[] input) {
+        assert input != null;
+        assert input.length > 0;
+        System.out.println(">>>");
+        System.out.println("Find maximum in primitive array: " + Arrays.toString(input));
+        System.out.println(">>>");
+
+        long maximum = input[0];
+
+        for (int i = 1; i < input.length; i++) {
+            if (input[i] > maximum)
+                maximum = input[i];
+        }
+
+        return maximum;
+    }
+
+    /**
+     * Find maximum value in Iterator.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    @Override public long findMaximumInIterator(Iterator<Long> input) {
+        assert input != null;
+        assert input.hasNext();
+
+        System.out.println(">>>");
+        System.out.println("Find maximum in iterator: " + input);
+        System.out.println(">>>");
+
+        long maximum = input.next();
+
+        while (input.hasNext()) {
+            Long val = input.next();
+
+            if (val > maximum)
+                maximum = val;
+        }
+
+        return maximum;
+    }
+
+    /**
+     * Find maximum value in Enumeration.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    @Override public long findMaximumInEnumeration(Enumeration<Long> input) {
+        assert input != null;
+        assert input.hasMoreElements();
+
+        System.out.println(">>>");
+        System.out.println("Find maximum in enumeration: " + input);
+        System.out.println(">>>");
+
+        long maximum = input.nextElement();
+
+        while (input.hasMoreElements()) {
+            Long val = input.nextElement();
+
+            if (val > maximum)
+                maximum = val;
+        }
+
+        return maximum;
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToValueTargetInterface.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToValueTargetInterface.java
new file mode 100644
index 0000000..161c250
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToValueTargetInterface.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.compute.gridify.GridifySetToValue;
+
+/**
+ * Test set-to-value target interface.
+ */
+public interface GridifySetToValueTargetInterface {
+    /**
+     * Find maximum value in collection.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    public Long findMaximum(Collection<Long> input);
+
+    /**
+     * Find maximum value in collection.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget")
+    public Long findMaximumInList(List<Long> input);
+
+    /**
+     * Find maximum value in collection.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2)
+    public Long findMaximumWithoutSplitSize(Collection<Long> input);
+
+    /**
+     * Find maximum value in collection.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget")
+    public Long findMaximumWithoutSplitSizeAndThreshold(Collection<Long> input);
+
+    /**
+     * Find maximum in array.
+     *
+     * @param input Input array.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    public Long findPrimesInArray(Long[] input);
+
+    /**
+     * Find maximum in primitive array.
+     *
+     * @param input Input array.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    public long findMaximumInPrimitiveArray(long[] input);
+
+    /**
+     * Find maximum value in Iterator.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    public long findMaximumInIterator(Iterator<Long> input);
+
+
+    /**
+     * Find maximum value in Enumeration.
+     *
+     * @param input Input collection.
+     * @return Maximum value.
+     */
+    @GridifySetToValue(igniteInstanceName = "GridifySetToValueTarget", threshold = 2, splitSize = 2)
+    public long findMaximumInEnumeration(Enumeration<Long> input);
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToXXXNonSpringAopSelfTest.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToXXXNonSpringAopSelfTest.java
new file mode 100644
index 0000000..c96355d
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToXXXNonSpringAopSelfTest.java
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+import org.junit.Test;
+
+/**
+ * To run this test with JBoss AOP make sure of the following:
+ *
+ * 1. The JVM is started with following parameters to enable jboss online weaving
+ *      (replace ${IGNITE_HOME} to you $IGNITE_HOME):
+ *      -javaagent:${IGNITE_HOME}libs/jboss-aop-jdk50-4.0.4.jar
+ *      -Djboss.aop.class.path=[path to grid compiled classes (Idea out folder) or path to ignite.jar]
+ *      -Djboss.aop.exclude=org,com -Djboss.aop.include=org.apache.ignite
+ *
+ * 2. The following jars should be in a classpath:
+ *      ${IGNITE_HOME}libs/javassist-3.x.x.jar
+ *      ${IGNITE_HOME}libs/jboss-aop-jdk50-4.0.4.jar
+ *      ${IGNITE_HOME}libs/jboss-aspect-library-jdk50-4.0.4.jar
+ *      ${IGNITE_HOME}libs/jboss-common-4.2.2.jar
+ *      ${IGNITE_HOME}libs/trove-1.0.2.jar
+ *
+ * To run this test with AspectJ APO make sure of the following:
+ *
+ * 1. The JVM is started with following parameters for enable AspectJ online weaving
+ *      (replace ${IGNITE_HOME} to you $IGNITE_HOME):
+ *      -javaagent:${IGNITE_HOME}/libs/aspectjweaver-1.7.2.jar
+ *
+ * 2. Classpath should contains the ${IGNITE_HOME}/modules/tests/config/aop/aspectj folder.
+ */
+@GridCommonTest(group = "AOP")
+public class GridifySetToXXXNonSpringAopSelfTest extends GridCommonAbstractTest {
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testGridifySetToSet() throws Exception {
+        try {
+            startGrid("GridifySetToSetTarget");
+            startGrid("GridifySetToSetTarget2");
+            startGrid("GridifySetToSetTarget3");
+
+            GridifySetToSetTarget target = new GridifySetToSetTarget();
+
+            Collection<Long> primesInSet = target.findPrimes(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Prime numbers in set '" + primesInSet + "'.");
+
+            primesInSet = target.findPrimesWithoutSplitSize(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Prime numbers w/o splitsize in set '" + primesInSet + "'.");
+
+            primesInSet = target.findPrimesWithoutSplitSizeAndThreshold(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Prime numbers w/o splitsize and threshold in set '" + primesInSet + "'.");
+
+            primesInSet = target.findPrimesInListWithoutSplitSizeAndThreshold(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Prime numbers in list w/o splitsize and threshold in set '" + primesInSet + "'.");
+
+            primesInSet = target.findPrimesInArrayListWithoutSplitSizeAndThreshold(
+                new ArrayList<>(Arrays.asList(2L, 3L, 4L, 6L)));
+
+            info(">>> Prime numbers in arraylist w/o splitsize and threshold in set '" + primesInSet + "'.");
+
+            Long[] primesInArr = target.findPrimesInArray(new Long[]{2L, 3L, 4L, 6L});
+
+            info(">>> Prime numbers in array '" + Arrays.asList(primesInArr) + "'.");
+
+            long[] primesInPrimArr = target.findPrimesInPrimitiveArray(new long[]{2L, 3L, 4L, 6L});
+
+            info(">>> Prime numbers in primitive array '" + primesInPrimArr + "'.");
+
+            Iterator<Long> primesInIter = target.findPrimesWithIterator(Arrays.asList(2L, 3L, 4L, 6L).iterator());
+
+            info(">>> Prime numbers in iterator '" + convert(primesInIter) + "'.");
+
+            Enumeration<Long> primesInEnum = target.findPrimesWithEnumeration(
+                new MathEnumerationAdapter<>(Arrays.asList(2L, 3L, 4L, 6L)));
+
+            info(">>> Prime numbers in enumeration '" + convert(primesInEnum) + "'.");
+        }
+        finally {
+            stopGrid("GridifySetToSetTarget");
+            stopGrid("GridifySetToSetTarget2");
+            stopGrid("GridifySetToSetTarget3");
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testGridifySetToValue() throws Exception {
+        try {
+            startGrid("GridifySetToValueTarget");
+            startGrid("GridifySetToValueTarget2");
+            startGrid("GridifySetToValueTarget3");
+
+            GridifySetToValueTarget target = new GridifySetToValueTarget();
+
+            Long max = target.findMaximum(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Maximum in collection '" + max + "'.");
+
+            max = target.findMaximumInList(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Maximum in list '" + max + "'.");
+
+            max = target.findMaximumWithoutSplitSize(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Maximum w/o splitsize in collection '" + max + "'.");
+
+            max = target.findMaximumWithoutSplitSizeAndThreshold(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Maximum w/o splitsize and threshold in collection '" + max + "'.");
+
+            max = target.findMaximumInIterator(Arrays.asList(2L, 3L, 4L, 6L).iterator());
+
+            info(">>> Maximum in iterator '" + max + "'.");
+
+            max = target.findMaximumInEnumeration(new MathEnumerationAdapter<>(Arrays.asList(2L, 3L, 4L, 6L)));
+
+            info(">>> Maximum in enumeration '" + max + "'.");
+        }
+        finally {
+            stopGrid("GridifySetToValueTarget");
+            stopGrid("GridifySetToValueTarget2");
+            stopGrid("GridifySetToValueTarget3");
+        }
+    }
+
+    /**
+     * Convert data to collection.
+     *
+     * @param iter Iterator.
+     * @return Collection.
+     */
+    private <T> Collection<T> convert(Iterator<T> iter) {
+        List<T> list = new ArrayList<>();
+
+        while (iter.hasNext())
+            list.add(iter.next());
+
+        return list;
+    }
+
+    /**
+     * Convert data to collection.
+     *
+     * @param iter Iterator.
+     * @return Collection.
+     */
+    private <T> Collection<T> convert(Enumeration<T> iter) {
+        List<T> list = new ArrayList<>();
+
+        while (iter.hasMoreElements())
+            list.add(iter.nextElement());
+
+        return list;
+    }
+
+    /**
+     * Enumeration adapter.
+     */
+    private static class MathEnumerationAdapter<T> implements Enumeration<T> {
+        /** */
+        private Iterator<T> iter;
+
+        /**
+         * Creates Enumeration.
+         *
+         * @param col Input collection.
+         */
+        MathEnumerationAdapter(Collection<T> col) {
+            iter = col.iterator();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean hasMoreElements() {
+            return iter.hasNext();
+        }
+
+        /** {@inheritDoc} */
+        @Override public T nextElement() {
+            return iter.next();
+        }
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToXXXSpringAopSelfTest.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToXXXSpringAopSelfTest.java
new file mode 100644
index 0000000..4239a56
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/GridifySetToXXXSpringAopSelfTest.java
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.compute.gridify.aop.spring.GridifySpringEnhancer;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+import org.junit.Test;
+
+/**
+ * To run this test with JBoss AOP make sure of the following:
+ *
+ * 1. The JVM is started with following parameters to enable jboss online weaving
+ *      (replace ${IGNITE_HOME} to you $IGNITE_HOME):
+ *      -javaagent:${IGNITE_HOME}libs/jboss-aop-jdk50-4.0.4.jar
+ *      -Djboss.aop.class.path=[path to grid compiled classes (Idea out folder) or path to ignite.jar]
+ *      -Djboss.aop.exclude=org,com -Djboss.aop.include=org.apache.ignite
+ *
+ * 2. The following jars should be in a classpath:
+ *      ${IGNITE_HOME}libs/javassist-3.x.x.jar
+ *      ${IGNITE_HOME}libs/jboss-aop-jdk50-4.0.4.jar
+ *      ${IGNITE_HOME}libs/jboss-aspect-library-jdk50-4.0.4.jar
+ *      ${IGNITE_HOME}libs/jboss-common-4.2.2.jar
+ *      ${IGNITE_HOME}libs/trove-1.0.2.jar
+ *
+ * To run this test with AspectJ APO make sure of the following:
+ *
+ * 1. The JVM is started with following parameters for enable AspectJ online weaving
+ *      (replace ${IGNITE_HOME} to you $IGNITE_HOME):
+ *      -javaagent:${IGNITE_HOME}/libs/aspectjweaver-1.7.2.jar
+ *
+ * 2. Classpath should contains the ${IGNITE_HOME}/modules/tests/config/aop/aspectj folder.
+ */
+@GridCommonTest(group = "AOP")
+public class GridifySetToXXXSpringAopSelfTest extends GridCommonAbstractTest {
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testGridifySetToSet() throws Exception {
+        try {
+            startGrid("GridifySetToSetTarget");
+            startGrid("GridifySetToSetTarget2");
+            startGrid("GridifySetToSetTarget3");
+
+            GridifySetToSetTargetInterface target = GridifySpringEnhancer.enhance(new GridifySetToSetTarget());
+
+            Collection<Long> primesInSet = target.findPrimes(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Prime numbers in set '" + primesInSet + "'.");
+
+            primesInSet = target.findPrimesWithoutSplitSize(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Prime numbers w/o 'splitsize' in set '" + primesInSet + "'.");
+
+            primesInSet = target.findPrimesWithoutSplitSizeAndThreshold(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Prime numbers w/o 'splitsize' and 'threshold' in set '" + primesInSet + "'.");
+
+            primesInSet = target.findPrimesInListWithoutSplitSizeAndThreshold(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Prime numbers in list w/o 'splitsize' and 'threshold' in set '" + primesInSet + "'.");
+
+            primesInSet = target.findPrimesInArrayListWithoutSplitSizeAndThreshold(
+                new ArrayList<>(Arrays.asList(2L, 3L, 4L, 6L)));
+
+            info(">>> Prime numbers in 'arraylist' w/o 'splitsize' and threshold in set '" + primesInSet + "'.");
+
+            Long[] primesInArr = target.findPrimesInArray(new Long[]{2L, 3L, 4L, 6L});
+
+            info(">>> Prime numbers in array '" + Arrays.asList(primesInArr) + "'.");
+
+            long[] primesInPrimArr = target.findPrimesInPrimitiveArray(new long[]{2L, 3L, 4L, 6L});
+
+            info(">>> Prime numbers in primitive array '" + primesInPrimArr + "'.");
+
+            Iterator<Long> primesInIter = target.findPrimesWithIterator(Arrays.asList(2L, 3L, 4L, 6L).iterator());
+
+            info(">>> Prime numbers in iterator '" + convert(primesInIter) + "'.");
+
+            Enumeration<Long> primesInEnum = target.findPrimesWithEnumeration(
+                new MathEnumerationAdapter<>(Arrays.asList(2L, 3L, 4L, 6L)));
+
+            info(">>> Prime numbers in enumeration '" + convert(primesInEnum) + "'.");
+        }
+        finally {
+            stopGrid("GridifySetToSetTarget");
+            stopGrid("GridifySetToSetTarget2");
+            stopGrid("GridifySetToSetTarget3");
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testGridifySetToValue() throws Exception {
+        try {
+            startGrid("GridifySetToValueTarget");
+            startGrid("GridifySetToValueTarget2");
+            startGrid("GridifySetToValueTarget3");
+
+            GridifySetToValueTargetInterface target = GridifySpringEnhancer.enhance(new GridifySetToValueTarget());
+
+            Long max = target.findMaximum(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Maximum in collection '" + max + "'.");
+
+            max = target.findMaximumInList(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Maximum in list '" + max + "'.");
+
+            max = target.findMaximumWithoutSplitSize(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Maximum w/o splitsize in collection '" + max + "'.");
+
+            max = target.findMaximumWithoutSplitSizeAndThreshold(Arrays.asList(2L, 3L, 4L, 6L));
+
+            info(">>> Maximum w/o splitsize and threshold in collection '" + max + "'.");
+
+            max = target.findMaximumInIterator(Arrays.asList(2L, 3L, 4L, 6L).iterator());
+
+            info(">>> Maximum in iterator '" + max + "'.");
+
+            max = target.findMaximumInEnumeration(new MathEnumerationAdapter<>(Arrays.asList(2L, 3L, 4L, 6L)));
+
+            info(">>> Maximum in enumeration '" + max + "'.");
+        }
+        finally {
+            stopGrid("GridifySetToValueTarget");
+            stopGrid("GridifySetToValueTarget2");
+            stopGrid("GridifySetToValueTarget3");
+        }
+    }
+
+    /**
+     * Convert data to collection.
+     *
+     * @param iter Iterator.
+     * @return Collection.
+     */
+    private <T> Collection<T> convert(Iterator<T> iter) {
+        List<T> list = new ArrayList<>();
+
+        while (iter.hasNext())
+            list.add(iter.next());
+
+        return list;
+    }
+
+    /**
+     * Convert data to collection.
+     *
+     * @param iter Iterator.
+     * @return Collection.
+     */
+    private <T> Collection<T> convert(Enumeration<T> iter) {
+        List<T> list = new ArrayList<>();
+
+        while (iter.hasMoreElements())
+            list.add(iter.nextElement());
+
+        return list;
+    }
+
+    /**
+     * Enumeration adapter.
+     */
+    private static class MathEnumerationAdapter<T> implements Enumeration<T> {
+        /** */
+        private Iterator<T> iter;
+
+        /**
+         * Creates Enumeration.
+         *
+         * @param col Input collection.
+         */
+        MathEnumerationAdapter(Collection<T> col) {
+            iter = col.iterator();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean hasMoreElements() {
+            return iter.hasNext();
+        }
+
+        /** {@inheritDoc} */
+        @Override public T nextElement() {
+            return iter.next();
+        }
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/NonSpringAopSelfTest.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/NonSpringAopSelfTest.java
new file mode 100644
index 0000000..f822f6d
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/NonSpringAopSelfTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+
+/**
+ * To run this test with JBoss AOP make sure of the following:
+ *
+ * 1. The JVM is started with following parameters to enable jboss online weaving
+ *      (replace ${IGNITE_HOME} to you $IGNITE_HOME):
+ *      -javaagent:${IGNITE_HOME}libs/jboss-aop-jdk50-4.0.4.jar
+ *      -Djboss.aop.class.path=[path to grid compiled classes (Idea out folder) or path to ignite.jar]
+ *      -Djboss.aop.exclude=org,com -Djboss.aop.include=org.apache.ignite
+ *
+ * 2. The following jars should be in a classpath:
+ *      ${IGNITE_HOME}libs/javassist-3.x.x.jar
+ *      ${IGNITE_HOME}libs/jboss-aop-jdk50-4.0.4.jar
+ *      ${IGNITE_HOME}libs/jboss-aspect-library-jdk50-4.0.4.jar
+ *      ${IGNITE_HOME}libs/jboss-common-4.2.2.jar
+ *      ${IGNITE_HOME}libs/trove-1.0.2.jar
+ *
+ * To run this test with AspectJ AOP make sure of the following:
+ *
+ * 1. The JVM is started with following parameters for enable AspectJ online weaving
+ *      (replace ${IGNITE_HOME} to you $IGNITE_HOME):
+ *      -javaagent:${IGNITE_HOME}/libs/optional/ignite-aop/aspectjweaver-1.7.2.jar
+ *
+ * 2. Classpath should contains the ${IGNITE_HOME}/modules/tests/config/aop/aspectj folder.
+ */
+@GridCommonTest(group = "AOP")
+public class NonSpringAopSelfTest extends AbstractAopTest {
+    /** {@inheritDoc} */
+    @Override protected Object target() {
+        return new TestAopTarget();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getTestIgniteInstanceName() {
+        return "TestAopTarget";
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/SpringAopSelfTest.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/SpringAopSelfTest.java
new file mode 100644
index 0000000..777e823
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/SpringAopSelfTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import org.apache.ignite.compute.gridify.aop.spring.GridifySpringEnhancer;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+
+/**
+ * Spring AOP test.
+ */
+@GridCommonTest(group = "AOP")
+public class SpringAopSelfTest extends AbstractAopTest {
+    /** {@inheritDoc} */
+    @Override protected Object target() {
+        return GridifySpringEnhancer.enhance(new TestAopTarget());
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getTestIgniteInstanceName() {
+        return "TestAopTargetInterface";
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Object targetWithUserClassLoader() throws Exception {
+        Object res = super.targetWithUserClassLoader();
+
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+
+        Thread.currentThread().setContextClassLoader(res.getClass().getClassLoader());
+
+        res = GridifySpringEnhancer.enhance(res);
+
+        Thread.currentThread().setContextClassLoader(cl);
+
+        return res;
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestAopTarget.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestAopTarget.java
new file mode 100644
index 0000000..4d37e89
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestAopTarget.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import org.apache.ignite.compute.gridify.Gridify;
+
+/**
+ * AOP test.
+ */
+public class TestAopTarget implements TestAopTargetInterface {
+    /**
+     * @param arg Argument.
+     * @return Result.
+     */
+    @Gridify(igniteInstanceName = "TestAopTarget")
+    @Override public int gridifyDefault(String arg) {
+        return Integer.parseInt(arg);
+    }
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     */
+    @Gridify(igniteInstanceName = "TestAopTarget", taskClass = TestGridifyTask.class)
+    @Override public int gridifyNonDefaultClass(String arg) {
+        return Integer.parseInt(arg);
+    }
+
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     */
+    @Gridify(igniteInstanceName = "TestAopTarget", taskName = TestGridifyTask.TASK_NAME)
+    @Override public int gridifyNonDefaultName(String arg) {
+        return Integer.parseInt(arg);
+    }
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     */
+    @Gridify(igniteInstanceName = "TestAopTarget", taskName = "")
+    @Override public int gridifyNoName(String arg) {
+        return 0;
+    }
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     * @throws TestGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "TestAopTarget")
+    @Override public int gridifyDefaultException(String arg) throws TestGridifyException {
+        throw new TestGridifyException(arg);
+    }
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     * @throws TestGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "TestAopTarget")
+    @Override public int gridifyDefaultResource(String arg) throws TestGridifyException {
+        int res = Integer.parseInt(arg);
+
+        Integer rsrcVal = getResource();
+
+        assert rsrcVal != null;
+        assert rsrcVal == res : "Invalid result [res=" + res + ", rsrc=" + rsrcVal + ']';
+
+        return res;
+    }
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     * @throws TestGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "TestAopTarget", taskClass = TestGridifyTask.class)
+    @Override public int gridifyNonDefaultClassResource(String arg) throws TestGridifyException {
+        assert getResource() != null;
+
+        return Integer.parseInt(arg);
+    }
+
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     * @throws TestGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "TestAopTarget", taskName = TestGridifyTask.TASK_NAME)
+    @Override public int gridifyNonDefaultNameResource(String arg) throws TestGridifyException {
+        assert getResource() != null;
+
+        return Integer.parseInt(arg);
+    }
+
+    /**
+     * @return Result.
+     * @throws TestGridifyException If failed.
+     */
+    private Integer getResource() throws TestGridifyException {
+        try (InputStream in = getClass().getResourceAsStream("test_resource.properties")) {
+            assert in != null;
+
+            Properties prop = new Properties();
+
+            prop.load(in);
+
+            String val = prop.getProperty("param1");
+
+            return Integer.parseInt(val);
+        }
+        catch (IOException e) {
+            throw new TestGridifyException("Failed to test load properties file.", e);
+        }
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestAopTargetInterface.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestAopTargetInterface.java
new file mode 100644
index 0000000..ab252df
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestAopTargetInterface.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.io.Serializable;
+import org.apache.ignite.compute.gridify.Gridify;
+
+/**
+ * Test AOP target interface.
+ */
+public interface TestAopTargetInterface extends Serializable {
+    /**
+     * @param arg Argument.
+     * @return Result.
+     */
+    @Gridify(igniteInstanceName = "TestAopTargetInterface")
+    public int gridifyDefault(String arg);
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     */
+    @Gridify(igniteInstanceName = "TestAopTargetInterface", taskName = TestGridifyTask.TASK_NAME)
+    public int gridifyNonDefaultName(String arg);
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     */
+    @Gridify(igniteInstanceName = "TestAopTargetInterface", taskClass = TestGridifyTask.class)
+    public int gridifyNonDefaultClass(String arg);
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     */
+    @Gridify(igniteInstanceName = "TestAopTargetInterface", taskName = "")
+    public int gridifyNoName(String arg);
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     * @throws TestGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "TestAopTargetInterface")
+    public int gridifyDefaultException(String arg) throws TestGridifyException;
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     * @throws TestGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "TestAopTargetInterface")
+    public int gridifyDefaultResource(String arg) throws TestGridifyException;
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     * @throws TestGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "TestAopTargetInterface", taskClass = TestGridifyTask.class)
+    public int gridifyNonDefaultClassResource(String arg) throws TestGridifyException;
+
+    /**
+     * @param arg Argument.
+     * @return Result.
+     * @throws TestGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "TestAopTargetInterface", taskName = TestGridifyTask.TASK_NAME)
+    public int gridifyNonDefaultNameResource(String arg) throws TestGridifyException;
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestGridifyException.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestGridifyException.java
new file mode 100644
index 0000000..aa340b6
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestGridifyException.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+/**
+ * Test gridify exception.
+ */
+public class TestGridifyException extends Exception {
+    /**
+     * @param msg Message.
+     */
+    public TestGridifyException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * @param msg Message.
+     * @param cause Exception cause.
+     */
+    public TestGridifyException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestGridifyJob.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestGridifyJob.java
new file mode 100644
index 0000000..3dd1b7f
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestGridifyJob.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.io.Serializable;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.compute.ComputeJobAdapter;
+import org.apache.ignite.resources.LoggerResource;
+
+/**
+ * Test gridify job.
+ */
+public class TestGridifyJob extends ComputeJobAdapter {
+    /** */
+    @LoggerResource
+    private IgniteLogger log;
+
+    /**
+     * @param arg Argument.
+     */
+    public TestGridifyJob(String arg) {
+        super(arg);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Serializable execute() {
+        if (log.isInfoEnabled())
+            log.info("Execute TestGridifyJob.execute(" + argument(0) + ')');
+
+        TestAopTarget target = new TestAopTarget();
+
+        try {
+            if ("1".equals(argument(0)))
+                return target.gridifyNonDefaultClass("10");
+            else if ("2".equals(argument(0)))
+                return target.gridifyNonDefaultName("20");
+            else if ("3".equals(argument(0)))
+                return target.gridifyNonDefaultClassResource("30");
+            else if ("4".equals(argument(0)))
+                return target.gridifyNonDefaultNameResource("40");
+        }
+        catch (TestGridifyException e) {
+            throw new RuntimeException("Failed to execute target method.", e);
+        }
+
+        assert false : "Argument must be equals to \"0\" [gridifyArg=" + argument(0) + ']';
+
+        // Never reached.
+        return null;
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestGridifyTask.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestGridifyTask.java
new file mode 100644
index 0000000..650f708
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/TestGridifyTask.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.compute.ComputeTaskName;
+import org.apache.ignite.compute.ComputeTaskSplitAdapter;
+import org.apache.ignite.compute.gridify.GridifyArgument;
+
+/**
+ * Test gridify task.
+ */
+@ComputeTaskName(TestGridifyTask.TASK_NAME)
+public class TestGridifyTask extends ComputeTaskSplitAdapter<GridifyArgument, Object> {
+    /** */
+    public static final String TASK_NAME = "org.apache.ignite.gridify.TestGridifyTask";
+
+    /** {@inheritDoc} */
+    @Override public Collection<? extends ComputeJob> split(int gridSize, GridifyArgument arg) {
+        assert arg.getMethodParameters().length == 1;
+
+        return Collections.singletonList(new TestGridifyJob((String)arg.getMethodParameters()[0]));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object reduce(List<ComputeJobResult> results) {
+        assert results.size() == 1;
+
+        return results.get(0).getData();
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/GridifyHierarchyTest.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/GridifyHierarchyTest.java
new file mode 100644
index 0000000..24f0d3b
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/GridifyHierarchyTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify.hierarchy;
+
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+/**
+ * Gridify hierarchy test.
+ */
+public class GridifyHierarchyTest extends GridCommonAbstractTest {
+    /** */
+    public GridifyHierarchyTest() {
+        super(true);
+    }
+
+    /** */
+    public void noneTestGridifyHierarchyProtected() {
+        Target target = new Target();
+
+        target.methodA();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testGridifyHierarchyPrivate() throws Exception {
+        Target target = new Target();
+
+        target.methodB();
+    }
+
+   /** {@inheritDoc} */
+    @Override public String getTestIgniteInstanceName() {
+        return "GridifyHierarchyTest";
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/SuperTarget.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/SuperTarget.java
new file mode 100644
index 0000000..af2ed37
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/SuperTarget.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify.hierarchy;
+
+import org.apache.ignite.compute.gridify.Gridify;
+
+/**
+ * Target base class.
+ */
+public abstract class SuperTarget {
+    /**
+     * @return Always returns "SuperTarget.methodA()".
+     */
+    @Gridify(igniteInstanceName = "GridifyHierarchyTest")
+    protected String methodA() {
+        System.out.println(">>> Called SuperTarget.methodA()");
+
+        return "SuperTarget.methodA()";
+    }
+
+    /**
+     * @return "SuperTarget.methodC()" string.
+     */
+    protected String methodB() {
+        return methodC();
+    }
+
+    /**
+     * @return "SuperTarget.methodC()" string.
+     */
+    @Gridify(igniteInstanceName = "GridifyHierarchyTest")
+    private String methodC() {
+        System.out.println(">>> Called SuperTarget.methodC()");
+
+        return "SuperTarget.methodC()";
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/Target.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/Target.java
new file mode 100644
index 0000000..2393fc2
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/Target.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.gridify.hierarchy;
+
+/**
+ * Target.
+ */
+public class Target extends SuperTarget {
+    /** {@inheritDoc} */
+    @Override protected String methodA() {
+        System.out.println(">>> Called Target.methodA()");
+
+        String res = super.methodA();
+
+        assert "SuperTarget.methodA()".equals(res) :
+            "Unexpected SuperTarget.methodA() apply result [res=" + res + ']';
+
+        return "Target.MethodA()";
+    }
+
+    /** {@inheritDoc} */
+    @Override protected String methodB() {
+        String res = super.methodB();
+
+        assert "SuperTarget.methodC()".equals(res) :
+            "Unexpected SuperTarget.methodB() apply result [res=" + res + ']';
+
+        return res;
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/package-info.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/package-info.java
new file mode 100644
index 0000000..eaf46b7
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/hierarchy/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 description. -->
+ * Contains internal tests or test related classes and interfaces.
+ */
+
+package org.apache.ignite.gridify.hierarchy;
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/package-info.java b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/package-info.java
new file mode 100644
index 0000000..06ae4ad
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 description. -->
+ * Contains internal tests or test related classes and interfaces.
+ */
+
+package org.apache.ignite.gridify;
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/gridify/test_resource.properties b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/test_resource.properties
new file mode 100644
index 0000000..15b218e
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/gridify/test_resource.properties
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+
+param1=1
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/internal/marshaller/optimized/OptimizedMarshallerAopTest.java b/modules/aop-ext/src/test/java/org/apache/ignite/internal/marshaller/optimized/OptimizedMarshallerAopTest.java
new file mode 100644
index 0000000..0a0efdd
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/internal/marshaller/optimized/OptimizedMarshallerAopTest.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.internal.marshaller.optimized;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.compute.gridify.Gridify;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.events.Event;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+import static org.apache.ignite.events.EventType.EVT_TASK_FINISHED;
+
+/**
+ * Test use GridOptimizedMarshaller and AspectJ AOP.
+ *
+ * The following configuration needs to be applied to enable AspectJ byte code
+ * weaving.
+ * <ul>
+ * <li>
+ *      JVM configuration should include:
+ *      <tt>-javaagent:[IGNITE_HOME]/libs/aspectjweaver-1.7.2.jar</tt>
+ * </li>
+ * <li>
+ *      Classpath should contain the <tt>[IGNITE_HOME]/modules/tests/config/aop/aspectj</tt> folder.
+ * </li>
+ * </ul>
+ */
+public class OptimizedMarshallerAopTest extends GridCommonAbstractTest {
+    /** */
+    private static final AtomicInteger cntr = new AtomicInteger();
+
+    /**
+     * Constructs a test.
+     */
+    public OptimizedMarshallerAopTest() {
+        super(false /* start grid. */);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        IgniteConfiguration cfg = new IgniteConfiguration();
+
+        cfg.setMarshaller(new OptimizedMarshaller());
+
+        G.start(cfg);
+
+        assert G.allGrids().size() == 1;
+    }
+
+    /**
+     * JUnit.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testUp() throws Exception {
+        G.ignite().events().localListen(new IgnitePredicate<Event>() {
+            @Override public boolean apply(Event evt) {
+                cntr.incrementAndGet();
+
+                return true;
+            }
+        }, EVT_TASK_FINISHED);
+
+        gridify1();
+
+        assertEquals("Method gridify() wasn't executed on grid.", 1, cntr.get());
+    }
+
+    /**
+     * Method grid-enabled with {@link org.apache.ignite.compute.gridify.Gridify} annotation.
+     * <p>
+     * Note that default {@code Gridify} configuration is used, so this method
+     * will be executed on remote node with the same argument.
+     */
+    @Gridify
+    private void gridify1() {
+        X.println("Executes on grid");
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/p2p/P2PGridifySelfTest.java b/modules/aop-ext/src/test/java/org/apache/ignite/p2p/P2PGridifySelfTest.java
new file mode 100644
index 0000000..f5cbf0c
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/p2p/P2PGridifySelfTest.java
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.p2p;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.compute.gridify.Gridify;
+import org.apache.ignite.configuration.DeploymentMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.testframework.GridTestClassLoader;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ *
+ */
+@SuppressWarnings({"ProhibitedExceptionDeclared"})
+@Ignore("https://issues.apache.org/jira/browse/IGNITE-13723")
+@GridCommonTest(group = "P2P")
+public class P2PGridifySelfTest extends GridCommonAbstractTest {
+    /** Current deployment mode. Used in {@link #getConfiguration(String)}. */
+    private DeploymentMode depMode;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        // Override P2P configuration to exclude Task and Job classes
+        cfg.setPeerClassLoadingLocalClassPathExclude(GridP2PTestTask.class.getName(), GridP2PTestJob.class.getName());
+
+        cfg.setDeploymentMode(depMode);
+
+        return cfg;
+    }
+
+    /**
+     * @param depMode deployment mode.
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("unchecked")
+    private void processTestBothNodesDeploy(DeploymentMode depMode) throws Exception {
+        int res = 0;
+
+        try {
+            this.depMode = depMode;
+
+            Ignite ignite1 = startGrid(1);
+            startGrid(2);
+
+            GridTestClassLoader tstClsLdr = new GridTestClassLoader(
+                Collections.singletonMap("org/apache/ignite/p2p/p2p.properties", "resource=loaded"),
+                getClass().getClassLoader(),
+                GridP2PTestTask.class.getName(), GridP2PTestJob.class.getName()
+            );
+
+            Class<? extends ComputeTask<?, ?>> taskCls1 = (Class<? extends ComputeTask<?, ?>>)tstClsLdr.loadClass(
+                GridP2PTestTask.class.getName());
+
+            ignite1.compute().localDeployTask(taskCls1, taskCls1.getClassLoader());
+
+            res = executeGridify(1);
+
+            ignite1.compute().undeployTask(taskCls1.getName());
+        }
+        finally {
+            stopGrid(2);
+            stopGrid(1);
+        }
+
+        // P2P deployment
+        assert res == 10 : "Invalid gridify result: " + res;
+    }
+
+    /**
+     * @param res Result.
+     * @return The same value as parameter has.
+     */
+    @Gridify(taskName = "org.apache.ignite.p2p.GridP2PTestTask",
+        igniteInstanceName = "org.apache.ignite.p2p.GridP2PGridifySelfTest1")
+    public int executeGridify(int res) {
+        return res;
+    }
+
+    /**
+     * @param depMode deployment mode.
+     * @throws Exception If failed.
+     */
+    private void processTestGridifyResource(DeploymentMode depMode) throws Exception {
+        try {
+            this.depMode = depMode;
+
+            startGrid(1);
+
+            Integer res = executeGridifyResource(1);
+
+            // P2P deployment
+            assert res != null : "res != null";
+            assert res == 1 : "Unexpected result [res=" + res + ", expected=0]";
+
+            info("Tests passed.");
+        }
+        finally {
+            stopGrid(1);
+        }
+    }
+
+    /**
+     * Note that this method sends instance of test class to remote node.
+     * Be sure that this instance does not have none-serializable fields or references
+     * to the objects that could not be instantiated like class loaders and so on.
+     *
+     * @param res Result.
+     * @return The same value as parameter has.
+     */
+    @Gridify(igniteInstanceName = "org.apache.ignite.p2p.GridP2PGridifySelfTest1")
+    public Integer executeGridifyResource(int res) {
+        String path = "org/apache/ignite/p2p/p2p.properties";
+
+        GridTestClassLoader tstClsLdr = new GridTestClassLoader(
+            GridP2PTestTask.class.getName(),
+            GridP2PTestJob.class.getName()
+        );
+
+        // Test property file load.
+        byte[] bytes = new byte[20];
+
+        try (InputStream in = tstClsLdr.getResourceAsStream(path)) {
+            if (in == null) {
+                System.out.println("Resource could not be loaded: " + path);
+
+                return -2;
+            }
+
+            in.read(bytes);
+        }
+        catch (IOException e) {
+            System.out.println("Failed to read from resource stream: " + e.getMessage());
+
+            return -3;
+        }
+
+        String rsrcVal = new String(bytes).trim();
+
+        System.out.println("Remote resource content is : " + rsrcVal);
+
+        if (!rsrcVal.equals("resource=loaded")) {
+            System.out.println("Invalid loaded resource value: " + rsrcVal);
+
+            return -4;
+        }
+
+        return res;
+    }
+
+    /**
+     * Test GridDeploymentMode.ISOLATED mode.
+     *
+     * @throws Exception if error occur.
+     */
+    @Test
+    public void testPrivateMode() throws Exception {
+        processTestBothNodesDeploy(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * Test GridDeploymentMode.ISOLATED mode.
+     *
+     * @throws Exception if error occur.
+     */
+    @Test
+    public void testIsolatedMode() throws Exception {
+        processTestBothNodesDeploy(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * Test GridDeploymentMode.CONTINUOUS mode.
+     *
+     * @throws Exception if error occur.
+     */
+    @Test
+    public void testContinuousMode() throws Exception {
+        processTestBothNodesDeploy(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * Test GridDeploymentMode.SHARED mode.
+     *
+     * @throws Exception if error occur.
+     */
+    @Test
+    public void testSharedMode() throws Exception {
+        processTestBothNodesDeploy(DeploymentMode.SHARED);
+    }
+
+    /**
+     * Test GridDeploymentMode.ISOLATED mode.
+     *
+     * @throws Exception if error occur.
+     */
+    @Test
+    public void testResourcePrivateMode() throws Exception {
+        processTestGridifyResource(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * Test GridDeploymentMode.ISOLATED mode.
+     *
+     * @throws Exception if error occur.
+     */
+    @Test
+    public void testResourceIsolatedMode() throws Exception {
+        processTestGridifyResource(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * Test GridDeploymentMode.CONTINUOUS mode.
+     *
+     * @throws Exception if error occur.
+     */
+    @Test
+    public void testResourceContinuousMode() throws Exception {
+        processTestGridifyResource(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * Test GridDeploymentMode.SHARED mode.
+     *
+     * @throws Exception if error occur.
+     */
+    @Test
+    public void testResourceSharedMode() throws Exception {
+        processTestGridifyResource(DeploymentMode.SHARED);
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/ignite/testsuites/IgniteAopSelfTestSuite.java b/modules/aop-ext/src/test/java/org/apache/ignite/testsuites/IgniteAopSelfTestSuite.java
new file mode 100644
index 0000000..abf9879
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/ignite/testsuites/IgniteAopSelfTestSuite.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.testsuites;
+
+import org.apache.ignite.gridify.BasicAopSelfTest;
+import org.apache.ignite.gridify.GridifySetToXXXNonSpringAopSelfTest;
+import org.apache.ignite.gridify.GridifySetToXXXSpringAopSelfTest;
+import org.apache.ignite.gridify.NonSpringAopSelfTest;
+import org.apache.ignite.gridify.SpringAopSelfTest;
+import org.apache.ignite.gridify.hierarchy.GridifyHierarchyTest;
+import org.apache.ignite.internal.marshaller.optimized.OptimizedMarshallerAopTest;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.tools.junit.JUnitTeamcityReporter;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.test.gridify.ExternalNonSpringAopSelfTest;
+
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_OVERRIDE_MCAST_GRP;
+
+/**
+ * AOP test suite.
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    // Test configuration.
+    BasicAopSelfTest.class,
+
+    SpringAopSelfTest.class,
+    NonSpringAopSelfTest.class,
+    GridifySetToXXXSpringAopSelfTest.class,
+    GridifySetToXXXNonSpringAopSelfTest.class,
+    ExternalNonSpringAopSelfTest.class,
+
+    OptimizedMarshallerAopTest.class,
+    GridifyHierarchyTest.class
+})
+public class IgniteAopSelfTestSuite {
+    /** */
+    @BeforeClass
+    public static void init() {
+        JUnitTeamcityReporter.suite = IgniteAopSelfTestSuite.class.getName();
+
+        // Examples
+        System.setProperty(IGNITE_OVERRIDE_MCAST_GRP, GridTestUtils.getNextMulticastGroup(IgniteAopSelfTestSuite.class));
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/SingleSplitTestJobTarget.java b/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/SingleSplitTestJobTarget.java
new file mode 100644
index 0000000..f3e63df
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/SingleSplitTestJobTarget.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.loadtests.direct.singlesplit;
+
+import org.apache.ignite.compute.ComputeTaskSession;
+import org.apache.ignite.compute.gridify.Gridify;
+import org.apache.loadtests.gridify.GridifyLoadTestTask;
+
+/**
+ * Single split test job target.
+ */
+public class SingleSplitTestJobTarget {
+    /**
+     * @param level Level.
+     * @param jobSes Job session.
+     * @return ALways returns {@code 1}.
+     */
+    @SuppressWarnings("unused")
+    @Gridify(taskClass = GridifyLoadTestTask.class, timeout = 10000)
+    public int executeLoadTestJob(int level, ComputeTaskSession jobSes) {
+        assert level > 0;
+        assert jobSes != null;
+
+        jobSes.setAttribute("1st", 10000);
+        jobSes.setAttribute("2nd", 10000);
+
+        return 1;
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/SingleSplitTestTask.java b/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/SingleSplitTestTask.java
new file mode 100644
index 0000000..e0384e0
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/SingleSplitTestTask.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.loadtests.direct.singlesplit;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobAdapter;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.compute.ComputeLoadBalancer;
+import org.apache.ignite.compute.ComputeTaskAdapter;
+import org.apache.ignite.compute.ComputeTaskSession;
+import org.apache.ignite.resources.LoadBalancerResource;
+import org.apache.ignite.resources.TaskSessionResource;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Single split test task.
+ */
+public class SingleSplitTestTask extends ComputeTaskAdapter<Integer, Integer> {
+    /** */
+    @TaskSessionResource
+    private ComputeTaskSession taskSes;
+
+    /** */
+    @LoadBalancerResource
+    private ComputeLoadBalancer balancer;
+
+    /** {@inheritDoc} */
+    @NotNull @Override public Map<? extends ComputeJob, ClusterNode> map(List<ClusterNode> subgrid, Integer arg) {
+        assert !subgrid.isEmpty() : "Subgrid cannot be empty.";
+
+        Map<ComputeJobAdapter, ClusterNode> jobs = new HashMap<>(subgrid.size());
+
+        taskSes.setAttribute("1st", "1");
+        taskSes.setAttribute("2nd", "2");
+
+        Collection<UUID> assigned = new ArrayList<>(subgrid.size());
+
+        for (int i = 0; i < arg; i++) {
+            ComputeJobAdapter job = new ComputeJobAdapter(1) {
+                /** */
+                @TaskSessionResource
+                private ComputeTaskSession jobSes;
+
+                /** {@inheritDoc} */
+                @Override public Object execute() {
+                    assert jobSes != null;
+
+                    Integer arg = this.<Integer>argument(0);
+
+                    assert arg != null;
+
+                    return new SingleSplitTestJobTarget().executeLoadTestJob(arg, jobSes);
+                }
+            };
+
+            ClusterNode node = balancer.getBalancedNode(job, null);
+
+            assert node != null;
+
+            assigned.add(node.id());
+
+            jobs.put(job, node);
+        }
+
+        taskSes.setAttribute("nodes", assigned);
+
+        return jobs;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Integer reduce(List<ComputeJobResult> results) {
+        int retVal = 0;
+
+        for (ComputeJobResult res : results) {
+            assert res.getException() == null : "Load test jobs can never fail: " + res;
+
+            retVal += (Integer)res.getData();
+        }
+
+        return retVal;
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/SingleSplitsLoadTest.java b/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/SingleSplitsLoadTest.java
new file mode 100644
index 0000000..b6d4de9
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/SingleSplitsLoadTest.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.loadtests.direct.singlesplit;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.compute.ComputeTaskFuture;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.loadtests.GridLoadTestStatistics;
+import org.apache.ignite.logger.log4j.Log4JLogger;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.config.GridTestProperties;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+import org.apache.log4j.Level;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Single split load test.
+ */
+// Load test.
+@Ignore("https://issues.apache.org/jira/browse/IGNITE-13728")
+@GridCommonTest(group = "Load Test")
+public class SingleSplitsLoadTest extends GridCommonAbstractTest {
+    /** */
+    public SingleSplitsLoadTest() {
+        super(true);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration() throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration();
+
+        cfg.setCommunicationSpi(new TcpCommunicationSpi());
+        cfg.setDiscoverySpi(new TcpDiscoverySpi());
+
+        Log4JLogger log = (Log4JLogger)cfg.getGridLogger().getLogger(null);
+
+        log.setLevel(Level.INFO);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return (getTestDurationInMinutes() + 5) * 60 * 1000;
+    }
+
+    /**
+     * @return Time for load test in minutes.
+     */
+    private int getTestDurationInMinutes() {
+        return Integer.valueOf(GridTestProperties.getProperty("load.test.duration"));
+    }
+
+    /**
+     * @return Number of threads for the test.
+     */
+    private int getThreadCount() {
+        return Integer.valueOf(GridTestProperties.getProperty("load.test.threadnum"));
+    }
+
+    /**
+     * Load test grid.
+     *
+     * @throws Exception If task execution failed.
+     */
+    @Test
+    public void testLoad() throws Exception {
+        final Ignite ignite = G.ignite(getTestIgniteInstanceName());
+
+        final long end = getTestDurationInMinutes() * 60 * 1000 + System.currentTimeMillis();
+
+        // Warm up.
+        ignite.compute().withTimeout(5000).execute(SingleSplitTestTask.class.getName(), 3);
+
+        info("Load test will be executed for '" + getTestDurationInMinutes() + "' mins.");
+        info("Thread count: " + getThreadCount());
+
+        final GridLoadTestStatistics stats = new GridLoadTestStatistics();
+
+        GridTestUtils.runMultiThreaded(new Runnable() {
+            /** {@inheritDoc} */
+            @Override public void run() {
+                while (end - System.currentTimeMillis() > 0) {
+                    long start = System.currentTimeMillis();
+
+                    try {
+                        int levels = 20;
+
+                        ComputeTaskFuture<Integer> fut = ignite.compute().executeAsync(
+                            new SingleSplitTestTask(), levels);
+
+                        int res = fut.get();
+
+                        if (res != levels)
+                            fail("Received wrong result [expected=" + levels + ", actual=" + res + ']');
+
+                        long taskCnt = stats.onTaskCompleted(fut, levels, System.currentTimeMillis() - start);
+
+                        if (taskCnt % 500 == 0)
+                            info(stats.toString());
+                    }
+                    catch (IgniteException e) {
+                        error("Failed to execute grid task.", e);
+
+                        fail();
+                    }
+                }
+            }
+        }, getThreadCount(), "grid-notaop-load-test");
+
+        info("Final test statistics: " + stats);
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/package-info.java b/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/package-info.java
new file mode 100644
index 0000000..88ee022
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/loadtests/direct/singlesplit/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 description. -->
+ * Contains internal tests or test related classes and interfaces.
+ */
+
+package org.apache.loadtests.direct.singlesplit;
diff --git a/modules/aop-ext/src/test/java/org/apache/loadtests/gridify/GridifyLoadTestJobTarget.java b/modules/aop-ext/src/test/java/org/apache/loadtests/gridify/GridifyLoadTestJobTarget.java
new file mode 100644
index 0000000..570a5af
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/loadtests/gridify/GridifyLoadTestJobTarget.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.loadtests.gridify;
+
+import org.apache.ignite.compute.gridify.Gridify;
+
+/**
+ * Gridify load test job target.
+ */
+public class GridifyLoadTestJobTarget {
+    /**
+     * @param level Level.
+     * @return Always returns {@code 1}.
+     */
+    @SuppressWarnings("unused")
+    @Gridify(taskClass = GridifyLoadTestTask.class, timeout = 20000)
+    public int executeLoadTestJob(int level) {
+        assert level > 0;
+
+        return 1;
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/loadtests/gridify/GridifyLoadTestTask.java b/modules/aop-ext/src/test/java/org/apache/loadtests/gridify/GridifyLoadTestTask.java
new file mode 100644
index 0000000..bbce64f
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/loadtests/gridify/GridifyLoadTestTask.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.loadtests.gridify;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobAdapter;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.compute.ComputeTaskSplitAdapter;
+import org.apache.ignite.compute.gridify.GridifyArgument;
+
+/**
+ * Gridify load test task.
+ */
+public class GridifyLoadTestTask extends ComputeTaskSplitAdapter<GridifyArgument, Integer> {
+    /** {@inheritDoc} */
+    @Override protected Collection<? extends ComputeJob> split(int gridSize, GridifyArgument arg) {
+        assert gridSize > 0 : "Subgrid cannot be empty.";
+
+        int jobsNum = (Integer)arg.getMethodParameters()[0];
+
+        assert jobsNum > 0;
+
+        Collection<ComputeJobAdapter> jobs = new ArrayList<>(gridSize);
+
+        for (int i = 0; i < jobsNum; i++)
+            jobs.add(new ComputeJobAdapter(1) {
+                @Override public Serializable execute() {
+                    Integer arg = this.<Integer>argument(0);
+
+                    assert arg != null;
+
+                    return new GridifyLoadTestJobTarget().executeLoadTestJob(arg);
+                }
+            });
+
+        return jobs;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Integer reduce(List<ComputeJobResult> results) {
+        int retVal = 0;
+
+        for (ComputeJobResult res : results) {
+            if (res.getException() != null) {
+                throw new IgniteException("Received exception in reduce method (load test jobs can never fail): " + res,
+                    res.getException());
+            }
+
+            retVal += (Integer)res.getData();
+        }
+
+        return retVal;
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/apache/loadtests/gridify/GridifySingleSplitLoadTest.java b/modules/aop-ext/src/test/java/org/apache/loadtests/gridify/GridifySingleSplitLoadTest.java
new file mode 100644
index 0000000..f8d0499
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/apache/loadtests/gridify/GridifySingleSplitLoadTest.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.loadtests.gridify;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.loadtests.GridLoadTestStatistics;
+import org.apache.ignite.logger.log4j.Log4JLogger;
+import org.apache.ignite.spi.communication.CommunicationSpi;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.DiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.config.GridTestProperties;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+import org.apache.log4j.Level;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Gridify single split load test.
+ */
+// Load test.
+@Ignore("https://issues.apache.org/jira/browse/IGNITE-13728")
+@GridCommonTest(group = "Load Test")
+public class GridifySingleSplitLoadTest extends GridCommonAbstractTest {
+    /** */
+    public GridifySingleSplitLoadTest() {
+        super(true);
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public String getTestIgniteInstanceName() {
+        // Gridify task has empty Ignite instance name by default so we need to change it
+        // here.
+        return null;
+    }
+
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration() throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration();
+
+        /* Uncomment following code if you start it manually. */
+        CommunicationSpi commSpi = new TcpCommunicationSpi();
+
+        cfg.setCommunicationSpi(commSpi);
+
+        DiscoverySpi discoSpi = new TcpDiscoverySpi();
+
+        cfg.setDiscoverySpi(discoSpi);
+        /*
+         */
+        @SuppressWarnings("TypeMayBeWeakened")
+        Log4JLogger log = (Log4JLogger)cfg.getGridLogger();
+
+        log.getLogger("org.apache.ignite").setLevel(Level.INFO);
+
+        return cfg;
+    }
+
+    /**
+     * @return Time for load test in minutes.
+     */
+    private int getTestDurationInMinutes() {
+        return Integer.valueOf(GridTestProperties.getProperty("load.test.duration"));
+    }
+
+    /**
+     * @return Number of threads for the test.
+     */
+    private int getThreadCount() {
+        return Integer.valueOf(GridTestProperties.getProperty("load.test.threadnum"));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return (getTestDurationInMinutes() + 1) * 60 * 1000;
+    }
+
+    /**
+     * Load test grid.
+     *
+     * @throws Exception If task execution failed.
+     */
+    @Test
+    public void testGridifyLoad() throws Exception {
+        Ignite ignite = G.ignite(getTestIgniteInstanceName());
+
+        ignite.compute().localDeployTask(GridifyLoadTestTask.class, GridifyLoadTestTask.class.getClassLoader());
+
+        final long end = getTestDurationInMinutes() * 60 * 1000 + System.currentTimeMillis();
+
+        // Warm up.
+        new GridifyLoadTestJobTarget().executeLoadTestJob(3);
+
+        info("Load test will be executed for '" + getTestDurationInMinutes() + "' mins.");
+        info("Thread count: " + getThreadCount());
+
+        final GridLoadTestStatistics stats = new GridLoadTestStatistics();
+
+        GridTestUtils.runMultiThreaded(new Runnable() {
+            @Override public void run() {
+                while (end - System.currentTimeMillis() > 0) {
+                    int levels = 3;
+
+                    int exp = factorial(levels);
+
+                    long start = System.currentTimeMillis();
+
+                    int res = new GridifyLoadTestJobTarget().executeLoadTestJob(exp);
+
+                    if (res != exp)
+                        fail("Received wrong result [expected=" + exp + ", actual=" + res + ']');
+
+                    long taskCnt = stats.onTaskCompleted(null, exp, System.currentTimeMillis() - start);
+
+                    if (taskCnt % 500 == 0)
+                        info(stats.toString());
+                }
+            }
+
+        }, getThreadCount(), "grid-load-test-thread");
+
+        info("Final test statistics: " + stats);
+    }
+
+    /**
+     * Calculates factorial.
+     *
+     * @param num Factorial to calculate.
+     * @return Factorial for the number passed in.
+     */
+    private int factorial(int num) {
+        assert num > 0;
+
+        return num == 1 ? 1 : num * factorial(num - 1);
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/test/gridify/ExternalAopTarget.java b/modules/aop-ext/src/test/java/org/test/gridify/ExternalAopTarget.java
new file mode 100644
index 0000000..62c3547
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/test/gridify/ExternalAopTarget.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.test.gridify;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import org.apache.ignite.compute.gridify.Gridify;
+
+/**
+ * AOP target.
+ */
+public class ExternalAopTarget {
+    /**
+     * @param arg Argument.
+     * @return Argument parsed to integer.
+     */
+    @Gridify(igniteInstanceName = "ExternalAopTarget")
+    public int gridifyDefault(String arg) {
+        return Integer.parseInt(arg);
+    }
+
+    /**
+     * @param arg Argument.
+     * @return Argument parsed to integer.
+     */
+    @Gridify(igniteInstanceName = "ExternalAopTarget", taskClass = ExternalGridifyTask.class)
+    public int gridifyNonDefaultClass(String arg) {
+        return Integer.parseInt(arg);
+    }
+
+
+    /**
+     * @param arg Argument.
+     * @return Argument parsed to integer.
+     */
+    @Gridify(igniteInstanceName = "ExternalAopTarget", taskName = ExternalGridifyTask.TASK_NAME)
+    public int gridifyNonDefaultName(String arg) {
+        return Integer.parseInt(arg);
+    }
+
+    /**
+     * @param arg Argument.
+     * @return ALways 0.
+     */
+    @Gridify(igniteInstanceName = "ExternalAopTarget", taskName = "myTask", taskClass = ExternalGridifyTask.class)
+    public int gridifyTaskClassAndTaskName(String arg) {
+        assert arg != null;
+
+        return 0;
+    }
+
+    /**
+     * @param arg Argument.
+     * @return No-op.
+     * @throws ExternalGridifyException Always.
+     */
+    @Gridify(igniteInstanceName = "ExternalAopTarget")
+    public int gridifyDefaultException(String arg) throws ExternalGridifyException {
+        throw new ExternalGridifyException(arg);
+    }
+
+    /**
+     * @param arg Argument.
+     * @return Argument parsed to integer.
+     * @throws ExternalGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "ExternalAopTarget")
+    public int gridifyDefaultResource(String arg) throws ExternalGridifyException {
+        getResource();
+
+        return Integer.parseInt(arg);
+    }
+
+    /**
+     * @param arg Argument.
+     * @return Argument parsed to integer.
+     * @throws ExternalGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "ExternalAopTarget", taskClass = ExternalGridifyTask.class)
+    public int gridifyNonDefaultClassResource(String arg) throws ExternalGridifyException {
+        getResource();
+
+        return Integer.parseInt(arg);
+    }
+
+
+    /**
+     * @param arg Argument.
+     * @return Argument parsed to integer.
+     * @throws ExternalGridifyException If failed.
+     */
+    @Gridify(igniteInstanceName = "ExternalAopTarget", taskName = ExternalGridifyTask.TASK_NAME)
+    public int gridifyNonDefaultNameResource(String arg) throws ExternalGridifyException {
+        getResource();
+
+        return Integer.parseInt(arg);
+    }
+
+    /**
+     * @throws ExternalGridifyException If failed.
+     */
+    private void getResource() throws ExternalGridifyException {
+        try (InputStream in = getClass().getResourceAsStream("test_resource.properties")) {
+            assert in != null;
+
+            Properties prop = new Properties();
+
+            prop.load(in);
+
+            String val = prop.getProperty("param1");
+
+            assert "1".equals(val);
+        }
+        catch (IOException e) {
+            throw new ExternalGridifyException("Failed to test load properties file.", e);
+        }
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/test/gridify/ExternalGridifyException.java b/modules/aop-ext/src/test/java/org/test/gridify/ExternalGridifyException.java
new file mode 100644
index 0000000..d6954c6
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/test/gridify/ExternalGridifyException.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.test.gridify;
+
+/**
+ * External gridify exception.
+ */
+public class ExternalGridifyException extends Exception {
+    /**
+     * @param msg Message.
+     */
+    public ExternalGridifyException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * @param msg Message.
+     * @param cause Exception cause.
+     */
+    public ExternalGridifyException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/test/gridify/ExternalGridifyTask.java b/modules/aop-ext/src/test/java/org/test/gridify/ExternalGridifyTask.java
new file mode 100644
index 0000000..1dfa7d8
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/test/gridify/ExternalGridifyTask.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.test.gridify;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobAdapter;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.compute.ComputeTaskSplitAdapter;
+import org.apache.ignite.compute.gridify.GridifyArgument;
+import org.apache.ignite.resources.LoggerResource;
+
+/**
+ * External gridify task.
+ */
+public class ExternalGridifyTask extends ComputeTaskSplitAdapter<GridifyArgument, Object> {
+    /** */
+    public static final String TASK_NAME = "org.test.gridify.ExternalGridifyTask";
+
+    /** {@inheritDoc} */
+    @Override public Collection<? extends ComputeJob> split(int gridSize, GridifyArgument arg) {
+        assert arg.getMethodParameters().length == 1;
+
+        return Collections.singletonList(new ComputeJobAdapter((String)arg.getMethodParameters()[0]) {
+            /** */
+            @LoggerResource
+            private IgniteLogger log;
+
+            /** {@inheritDoc} */
+            @Override public Serializable execute() {
+                if (log.isInfoEnabled())
+                    log.info("Execute TestGridifyJob.execute(" + argument(0) + ')');
+
+                ExternalAopTarget target = new ExternalAopTarget();
+
+                try {
+                    if ("1".equals(argument(0)))
+                        return target.gridifyNonDefaultClass("10");
+                    else if ("2".equals(argument(0)))
+                        return target.gridifyNonDefaultName("20");
+                    else if ("3".equals(argument(0)))
+                        return target.gridifyNonDefaultClassResource("30");
+                    else if ("4".equals(argument(0)))
+                        return target.gridifyNonDefaultNameResource("40");
+                }
+                catch (ExternalGridifyException e) {
+                    throw new RuntimeException("Failed to execute target method.", e);
+                }
+
+                assert false : "Argument must be equals to \"0\" [gridifyArg=" + argument(0) + ']';
+
+                // Never reached.
+                return null;
+            }
+        });
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object reduce(List<ComputeJobResult> results) {
+        assert results.size() == 1;
+
+        return results.get(0).getData();
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/test/gridify/ExternalNonSpringAopSelfTest.java b/modules/aop-ext/src/test/java/org/test/gridify/ExternalNonSpringAopSelfTest.java
new file mode 100644
index 0000000..41ba08d
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/test/gridify/ExternalNonSpringAopSelfTest.java
@@ -0,0 +1,570 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.test.gridify;
+
+import org.apache.ignite.configuration.DeploymentMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.gridify.TestGridifyException;
+import org.apache.ignite.gridify.TestGridifyTask;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.spi.deployment.local.LocalDeploymentSpi;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+import org.junit.Test;
+
+/**
+ * To run this test with JBoss AOP make sure of the following:
+ *
+ * 1. The JVM is started with following parameters to enable jboss online weaving
+ *      (replace ${IGNITE_HOME} to you $IGNITE_HOME):
+ *      -javaagent:${IGNITE_HOME}libs/jboss-aop-jdk50-4.0.4.jar
+ *      -Djboss.aop.class.path=[path to grid compiled classes (Idea out folder) or path to ignite.jar]
+ *      -Djboss.aop.exclude=org,com -Djboss.aop.include=org.apache.ignite
+ *
+ * 2. The following jars should be in a classpath:
+ *      ${IGNITE_HOME}libs/javassist-3.x.x.jar
+ *      ${IGNITE_HOME}libs/jboss-aop-jdk50-4.0.4.jar
+ *      ${IGNITE_HOME}libs/jboss-aspect-library-jdk50-4.0.4.jar
+ *      ${IGNITE_HOME}libs/jboss-common-4.2.2.jar
+ *      ${IGNITE_HOME}libs/trove-1.0.2.jar
+ *
+ * To run this test with AspectJ AOP make sure of the following:
+ *
+ * 1. The JVM is started with following parameters for enable AspectJ online weaving
+ *      (replace ${IGNITE_HOME} to you $IGNITE_HOME):
+ *      -javaagent:${IGNITE_HOME}/libs/aspectjweaver-1.7.2.jar
+ *
+ * 2. Classpath should contains the ${IGNITE_HOME}/modules/tests/config/aop/aspectj folder.
+ */
+@GridCommonTest(group = "AOP")
+public class ExternalNonSpringAopSelfTest extends GridCommonAbstractTest {
+    /** */
+    private DeploymentMode depMode = DeploymentMode.PRIVATE;
+
+    /** */
+    public ExternalNonSpringAopSelfTest() {
+        super(/**start grid*/false);
+    }
+
+    /**
+     * @return External AOP target.
+     */
+    protected ExternalAopTarget getTarget() {
+        return new ExternalAopTarget();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    private void deployTask() throws Exception {
+        G.ignite(getTestIgniteInstanceName()).compute().localDeployTask(TestGridifyTask.class,
+            TestGridifyTask.class.getClassLoader());
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultPrivate() throws Exception {
+        checkDefault(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultIsolated() throws Exception {
+        checkDefault(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultContinuous() throws Exception {
+        checkDefault(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultShared() throws Exception {
+        checkDefault(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassPrivate() throws Exception {
+        checkNonDefaultClass(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassIsolated() throws Exception {
+        checkNonDefaultClass(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultContinuous() throws Exception {
+        checkNonDefaultClass(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultShared() throws Exception {
+        checkNonDefaultClass(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNamePrivate() throws Exception {
+        checkNonDefaultName(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameIsolated() throws Exception {
+        checkNonDefaultName(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameContinuous() throws Exception {
+        checkNonDefaultName(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameShared() throws Exception {
+        checkNonDefaultName(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testTaskNameAndTaskClassPrivate() throws Exception {
+        checkTaskNameAndTaskClass(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testTaskNameAndTaskClassIsolated() throws Exception {
+        checkTaskNameAndTaskClass(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testTaskNameAndTaskClassContinuous() throws Exception {
+        checkTaskNameAndTaskClass(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testTaskNameAndTaskClassShared() throws Exception {
+        checkTaskNameAndTaskClass(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultExceptionPrivate() throws Exception {
+        checkDefaultException(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultExceptionIsolated() throws Exception {
+        checkDefaultException(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultExceptionContinuous() throws Exception {
+        checkDefaultException(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultExceptionShared() throws Exception {
+        checkDefaultException(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourcePrivate() throws Exception {
+        checkDefaultResource(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceIsolated() throws Exception {
+        checkDefaultResource(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceContinuous() throws Exception {
+        checkDefaultResource(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testDefaultResourceShared() throws Exception {
+        checkDefaultResource(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassResourcePrivate() throws Exception {
+        checkNonDefaultClassResource(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassResourceIsolated() throws Exception {
+        checkNonDefaultClassResource(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassResourceContinuous() throws Exception {
+        checkNonDefaultClassResource(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultClassResourceShared() throws Exception {
+        checkNonDefaultClassResource(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameResourcePrivate() throws Exception {
+        checkNonDefaultNameResource(DeploymentMode.PRIVATE);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameResourceIsolated() throws Exception {
+        checkNonDefaultNameResource(DeploymentMode.ISOLATED);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameResourceContinuous() throws Exception {
+        checkNonDefaultNameResource(DeploymentMode.CONTINUOUS);
+    }
+
+    /**
+     * @throws Exception If test failed.
+     */
+    @Test
+    public void testNonDefaultNameResourceShared() throws Exception {
+        checkNonDefaultNameResource(DeploymentMode.SHARED);
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkDefault(DeploymentMode depMode) throws Exception {
+        try {
+            this.depMode = depMode;
+
+            info("Start Gridify test with Default AOP Task in Deployment Mode : " + depMode);
+
+            startGrid();
+
+            deployTask();
+
+            int res = getTarget().gridifyDefault("1");
+
+            if (res != 1)
+                fail("Method gridifyDefault returns wrong value [result=" + res + ", expect=1]");
+
+            info("Executed @Gridify method gridifyDefault(1) [result=" + res + ']');
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkNonDefaultClass(DeploymentMode depMode) throws Exception {
+        try {
+            this.depMode = depMode;
+
+            info("Start Gridify test with Test AOP Task in Deployment Mode : " + depMode);
+
+            startGrid();
+
+            deployTask();
+
+            int res = getTarget().gridifyNonDefaultClass("1");
+
+            if (res != 10)
+                fail("Method gridifyNonDefault returns wrong value [result=" + res + ", expect=1]");
+
+            info("Executed @Gridify method gridifyNonDefaultClass(0) [result=" + res + ']');
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkNonDefaultName(DeploymentMode depMode) throws Exception {
+        try {
+            this.depMode = depMode;
+
+            info("Start Gridify test with Test AOP Task in Deployment Mode : " + depMode);
+
+            startGrid();
+
+            deployTask();
+
+            int res = getTarget().gridifyNonDefaultName("2");
+
+            if (res != 20)
+                fail("Method gridifyNonDefault returns wrong value [result=" + res + ", expect=2]");
+
+            info("Executed @Gridify method gridifyNonDefaultName(0) [result=" + res + ']');
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     */
+    private void checkTaskNameAndTaskClass(DeploymentMode depMode) {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Test AOP Task in Deployment Mode : " + depMode);
+
+        try {
+            startGrid();
+
+            deployTask();
+
+            getTarget().gridifyTaskClassAndTaskName("3");
+
+            assert false : "No exception thrown";
+        }
+        catch (Exception e) {
+            info("Got expected exception: " + e);
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     */
+    private void checkDefaultException(DeploymentMode depMode) {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Default AOP Task and exception in Deployment Mode : " + depMode);
+
+        boolean isException = false;
+
+        try {
+            startGrid();
+
+            deployTask();
+
+            getTarget().gridifyDefaultException("0");
+        }
+        catch (ExternalGridifyException e) {
+            info("@Gridify method gridifyDefaultException(0) returns exception: " + e);
+
+            isException = true;
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+
+            fail("@Gridify method gridifyDefaultException(0) returns exception [exception" + e +
+                ", expect=" + TestGridifyException.class.getName() + ']');
+        }
+        finally {
+            stopGrid();
+        }
+
+        if (!isException)
+            fail("@Gridify method gridifyDefaultException(0) does not return any exception.");
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkDefaultResource(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Default AOP Task in Deployment Mode : " + depMode);
+
+        try {
+            startGrid();
+
+            deployTask();
+
+            int res = getTarget().gridifyDefaultResource("0");
+
+            if (res != 0)
+                fail("Method gridifyDefaultResource returns wrong value [result=" + res + ", expect=0]");
+
+            info("Executed @Gridify method gridifyDefaultResource(0) [result=" + res + ']');
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkNonDefaultClassResource(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Test AOP Task in Deployment Mode : " + depMode);
+
+        try {
+            startGrid();
+
+            deployTask();
+
+            int res = getTarget().gridifyNonDefaultClassResource("3");
+
+            if (res != 30)
+                fail("Method gridifyNonDefaultClassResource returns wrong value [result=" + res + ", expect=3]");
+
+            info("Executed @Gridify method gridifyNonDefaultClassResource(3) [result=" + res + ']');
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @param depMode Deployment mode to use.
+     * @throws Exception If failed.
+     */
+    private void checkNonDefaultNameResource(DeploymentMode depMode) throws Exception {
+        this.depMode = depMode;
+
+        info("Start Gridify test with Test AOP Task in Deployment Mode : " + depMode);
+
+        try {
+            startGrid();
+
+            deployTask();
+
+            int res = getTarget().gridifyNonDefaultNameResource("4");
+
+            if (res != 40)
+                fail("Method gridifyNonDefaultNameResource returns wrong value [result=" + res + ", expect=4]");
+
+            info("Executed @Gridify method gridifyNonDefaultNameResource(4) [result=" + res + ']');
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration() throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration();
+        cfg.setDeploymentSpi(new LocalDeploymentSpi());
+
+        cfg.setMetricsUpdateFrequency(500);
+
+        cfg.setDeploymentMode(depMode);
+
+        return cfg;
+    }
+
+    /**
+     * @return Test Ignite instance name.
+     */
+    @Override public String getTestIgniteInstanceName() {
+        return "ExternalAopTarget";
+    }
+}
diff --git a/modules/aop-ext/src/test/java/org/test/gridify/package-info.java b/modules/aop-ext/src/test/java/org/test/gridify/package-info.java
new file mode 100644
index 0000000..8c8cf49
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/test/gridify/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 description. -->
+ * Contains internal tests or test related classes and interfaces.
+ */
+
+package org.test.gridify;
diff --git a/modules/aop-ext/src/test/java/org/test/gridify/test_resource.properties b/modules/aop-ext/src/test/java/org/test/gridify/test_resource.properties
new file mode 100644
index 0000000..2426275
--- /dev/null
+++ b/modules/aop-ext/src/test/java/org/test/gridify/test_resource.properties
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+
+# Resource file for gridify test.
+
+param1=1
diff --git a/pom.xml b/pom.xml
index f2c865a..027e2c5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,6 +56,7 @@
         <module>modules/topology-validator-ext</module>
         <module>modules/hibernate-ext</module>
         <module>modules/geospatial-ext</module>
+        <module>modules/aop-ext</module>
     </modules>
 
     <profiles>