{"id":416,"date":"2011-12-12T01:43:28","date_gmt":"2011-12-12T00:43:28","guid":{"rendered":"http:\/\/doanduyhai.wordpress.com\/?p=416"},"modified":"2011-12-12T01:43:28","modified_gmt":"2011-12-12T00:43:28","slug":"advanced-aspectj-part-ii-inter-type-declaration","status":"publish","type":"post","link":"https:\/\/www.doanduyhai.com\/blog\/?p=416","title":{"rendered":"Advanced AspectJ Part II : Inter-type declaration"},"content":{"rendered":"<p>In this article, we discuss about another ApectJ advanced feature: inter-type declaration (<strong>ITD<\/strong>), or more commonly called <strong>member introduction<\/strong>.<\/p>\n<p>In essence, this feature lets you &#8220;<em>inject<\/em>&#8221; new fields or methods into an existing class using an aspect. <\/p>\n<p>With ITD you can for example achieve <em>virtual multiple inheritance<\/em> or <em>mixin<\/em>. It is extremely powerfull but also very bug-prone because it somehow breaks basic Java encapsulation rules.<\/p>\n<p><!--more--><\/p>\n<h1>I Basic rules<\/h1>\n<p>It is possible to introduce into a Java class:<\/p>\n<ul>\n<li>field (final or not)<\/li>\n<li>method<\/li>\n<li>interface<\/li>\n<li>constructor (as well!)<\/li>\n<\/ul>\n<p>It is possible to introduce into a Java interface:<\/p>\n<ul>\n<li>method default implementation (yes, it&#8217;s very counter-intuitive with respect to the Java standard rules)<\/li>\n<li>non final fields<\/li>\n<\/ul>\n<p>While introducing field, method or constructor, the following access modifiers are allowed:<\/p>\n<ul>\n<li><strong>private<\/strong>: the introduced member belongs to the target class but it it &#8220;private&#8221; with respect to the introducing aspect. In other words this member is <strong>only visible to the aspect, not to the target class!<\/strong><\/li>\n<li><strong>public<\/strong>: the introduced member is visible to any class and aspect<\/li>\n<li><strong>default package protected<\/strong>: the introduced member is visible to any class and aspect in the <strong>same package of the declaring aspect<\/strong> (and not the package of the target class)<\/li>\n<\/ul>\n<p>If their is one thing to remember from access modifier, it&#8217;s that their semantic applies <em>with respect to the declaring aspect<\/em>, and not to the target. A private introduced member is private to the aspect.<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2011\/12\/aspectitd_private_field.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2011\/12\/aspectitd_private_field.png\" alt=\"\" title=\"AspectITD_private_field\" width=\"581\" height=\"192\" class=\"aligncenter size-full wp-image-422\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2011\/12\/aspectitd_private_field.png 581w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2011\/12\/aspectitd_private_field-300x99.png 300w\" sizes=\"(max-width: 581px) 100vw, 581px\" \/><\/a><\/p>\n<p>The syntax to introduce a member is:<\/p>\n<ul>\n<li><strong>for a field<\/strong> : <em>[access modifier]<\/em> <strong>TargetClass<\/strong>.<em>introducedFieldName<\/em><\/li>\n<li><strong>for a method\/constructor<\/strong> : <em>[access modifier]<\/em> <strong>TargetClass<\/strong>.<em>introducedMethodName(..) { \/\/method body }<\/em><\/li>\n<\/ul>\n<p>where <em>[access modifier]<\/em> can be: <strong>private<\/strong>, <strong>public <\/strong>or nothing (aspect package-protected)<br \/>\n&nbsp;<\/p>\n<h1>II Naming conflicts<\/h1>\n<p>By injecting members into a class, we are likely to run into conflicts if the target class already declares a member with the same name and same type.<\/p>\n<p>If we introduce a private field into the target class which already contaisn the same field declared as private, there is indeed no conflict. <strong>The &#8220;introduced&#8221; field is only visible from the declaring aspect and the original private field is only visible within the target class.<\/strong><\/p>\n<p>Exemple:<\/p>\n<pre class=\"brush: java; highlight: [5,10]; title: ; wrap-lines: false; notranslate\" title=\"\">\npackage com.test;\n\npublic class TestITDClass\n{\n\tprivate String myField;\n}\n\npublic aspect ITDAspect\n{\n\tprivate String TestITDClass.myField;\n}\n<\/pre>\n<p>In the above example, the base class <strong>TestITDClass<\/strong> has a private field <em>myField<\/em>. The <strong>ITDAspect<\/strong> introduces another <em>myField<\/em> field with aspect-related private visibility.<\/p>\n<p>The decompiled class file generated after compile-time weaving shows:<\/p>\n<pre class=\"brush: java; highlight: [3,4,8]; title: ; wrap-lines: false; notranslate\" title=\"\">\npublic class TestITDClass\n{\n  private String myField;\n  public String ajc$interField$com_test_aspect_ITDAspect$myField;\n\n  public TestITDClass()\n  {   \n    ITDAspect.ajc$interFieldInit$com_test_ITDAspect$com_test_TestITDClass$myField(this);\n  }\n}\n<\/pre>\n<p>Indeed, the original myField field of the target class is untouched. What AspectJ did is to inject a new public String field <em>ajc$interField$com_test_aspect_ITDAspect$myField<\/em> instead.<\/p>\n<p>Please notice that the injected field name is built using the canonical aspect name and target class name, all the dots (.) being replaced by underscores (_).<\/p>\n<p>Now, if the target class declares a <strong>public<\/strong> <em>myField<\/em> field and in the aspect code, we access <em>targetInstance.myField<\/em>, there will be an ambiguity. Which field should be returned ? The original <em>myField<\/em> field or the injected <em>ajc$interField$com_test_aspect_ITDAspect$myField<\/em>?<\/p>\n<p>In such case, it is simply <strong>forbidden<\/strong> since there is no way for the AspectJ compiler to distinguish between both fields. It is similar if you try to introduce a method with the same name and same signature. <strong>Introducing a method with the same name but different signature(parameters or returned type) is fine<\/strong>; it is as if you overload a method with different parameters or with covariant returned type.<\/p>\n<blockquote><p>It is not possible to inject a field (public or private whatever) into a target class if the latter already declared a <strong>public<\/strong> field with the same name (event with a different type)<\/p><\/blockquote>\n<blockquote><p>It is not possible to inject a method(public or private whatever) into a target class if the latter already declared a <strong>public<\/strong> method with the <strong>same name, same parameters signature and returned type<\/strong><\/p><\/blockquote>\n<h1>III Introducing members into interfaces<\/h1>\n<p>Similar to classes, it is also possible to inject members to an interface, with some differences:<\/p>\n<ul>\n<li>vanilla Java interfaces only allow final fields whereas with AspectJ you can inject <strong>non-final<\/strong> fields to interfaces!<\/li>\n<li>vanilla Java interfaces only allow method signature declaration wheraeas with AspectJ you can inject <strong>default implementation<\/strong> for a method<\/li>\n<p>!<\/ul>\n<p>Let&#8217;s define an interface and inject a field and method implementation using AspectJ:<\/p>\n<pre class=\"brush: java; highlight: [7,9,10]; title: ; wrap-lines: false; notranslate\" title=\"\">\npackage com.test;\n\npublic interface TestITDInterface\n{\n\tpublic String getInjectedMethod();\n\t\n\t static aspect TestITDInterfaceImpl\n\t {\n\t\t public String myInjectedField;\n\t\t public String TestITDInterface.getInjectedMethod()\n\t\t {\n\t\t\t return &amp;quot;Injected method&amp;quot;;\n\t\t }\n\t }\n}\n\npublic class TestITDClass implements TestITDInterface\n{\n\n\tpublic static void main(String[] args)\n\t{\n\t\tTestITDClass test = new TestITDClass();\n\t\tSystem.out.println(&amp;quot;getInjectedMethod = &amp;quot; + test.getInjectedMethod());\n\t}\n}\n<\/pre>\n<p>We define and <strong>TestITDInterface<\/strong> interface declaring a <em>getInjectedMethod()<\/em> method. Inside the same interface file, we define a <strong>nested aspect TestITDInterfaceImpl<\/strong>. This nested aspect must be static as per convention.<\/p>\n<p>Inside the <strong>TestITDInterfaceImpl<\/strong> aspect, we inject a field <em>myInjectedField<\/em> and we provide a concrete implementation for the <em>getInjectedMethod()<\/em> method.<\/p>\n<p>When running the class <strong>TestITDClass<\/strong>, we get as expected:<\/p>\n<p><code>getInjectedMethod = Injected method<\/code><br \/>\n&nbsp;<\/p>\n<h1>IV Logger with ITD<\/h1>\n<p>In this chapter, we&#8217;ll inject a logger into any class using AspectJ ITD.<\/p>\n<p>First we define the <em>Loggable<\/em> interface<\/p>\n<pre class=\"brush: java; title: ; wrap-lines: false; notranslate\" title=\"\">\npublic interface Loggable {}\n<\/pre>\n<p>Any class implementing this interface would have an injected logger.<\/p>\n<p>Now let&#8217;s create an aspect for the job<\/p>\n<pre class=\"brush: java; highlight: [3,5,10,15,16,20]; title: ; wrap-lines: false; notranslate\" title=\"\">\npublic aspect LoggerInjectionITDAspect\n{\n\tprivate Logger Loggable.logger;\n\n\tpublic Logger Loggable.getLogger()\n\t{\n\t\treturn logger;\n\t}\n\n\tpublic Logger Loggable.getLogger(String customLogger)\n\t{\n\t\treturn Logger.getLogger(customLogger);\n\t}\n\t\n\tpointcut objectConstruction(TestInjectedLoggerITD object) : \n\t\tinitialization(Loggable+.new(..)) &amp;amp;&amp;amp; this(object);\n\t\n\tafter(TestInjectedLoggerITD object) : objectConstruction(object)\n\t{\n\t\tobject.logger = Logger.getLogger(object.getClass().getCanonicalName());\n\t}\n\t\n}\n<\/pre>\n<p>The aspect injects:<\/p>\n<ul>\n<li>a <em>logger<\/em> field (<strong>line 3<\/strong>)<\/li>\n<li>a public method <em>getLogger()<\/em> with no argument <strong>(line 5<\/strong>)<\/li>\n<li>a public method <em>getLogger(String customLogger)<\/em> (<strong>line 10<\/strong>)<\/li>\n<\/ul>\n<p>More interesting is the pointcut <em>objectConstruction()<\/em> definition. This pointcut intercepts the <strong>instanciation<\/strong> (call to <em>new(..)<\/em> constructor) of any class implementing the <strong>Loggable<\/strong> interface (<em>Loggable+<\/em> means any subtype of Loggable) and retrieves the target instance in the pointcut context (<strong>lines 15 &amp; 16<\/strong>).<\/p>\n<p>After the initialization of the object, the aspect will create the default logger using the canonical class name as logger name and save it to the injected <em>logger<\/em> field (<strong>line 20<\/strong>).<\/p>\n<p>A call to <em>getLogger()<\/em> will return the injected <em>logger<\/em> field.<br \/>\nA call to <em>getLogger(String customLogger)<\/em> will build a new Logger instance based on the passed customLogger string and return this instance.<\/p>\n<p>Below is how the injected logger is called in a POJO:<\/p>\n<pre class=\"brush: java; highlight: [5,7,15,16]; title: ; wrap-lines: false; notranslate\" title=\"\">\npublic class TestInjectedLoggerITD implements Loggable\n{\n\tpublic void instanceLoggerITD()\n\t{\n\t\tthis.getLogger().info(&amp;quot;Test Logger ITD instance &amp;quot; + this.getLogger());\n\n\t\tthis.getLogger(&amp;quot;testLogger&amp;quot;).info(&amp;quot;Test customLogger ITD instance &amp;quot; + this.getLogger(&amp;quot;testLogger&amp;quot;));\n\t}\n\n\tpublic static void main(String[] args)\n\t{\n\t\tTestInjectedLoggerITD testInjectedLoggerITD1 = new TestInjectedLoggerITD();\n\t\tTestInjectedLoggerITD testInjectedLoggerITD2 = new TestInjectedLoggerITD();\n\n\t\ttestInjectedLoggerITD1.instanceLoggerITD();\n\t\ttestInjectedLoggerITD2.instanceLoggerITD();\n\t}\n}\n<\/pre>\n<p>The method  instanceLoggerITD() will test the usage of default injected logger and custom name logger (<strong>lines 5 &amp; 7<\/strong>).<\/p>\n<p>Please notice how the <strong>TestInjectedLoggerITD<\/strong> class makes use of the <em>getLogger()<\/em> and <em>getLogger(String customLogger)<\/em> although they have never been declared in the <strong>Loggable<\/strong> interface. It&#8217;s the magic from AspectJ ITD.<\/p>\n<p>The execution output gives:<\/p>\n<p><code>INFO  [01:42:18,484] com.test.TestInjectedLoggerITD@instanceLoggerITD: Test Logger ITD instance org.apache.log4j.Logger@<strong>1ab28fe<\/strong><br \/>\nINFO  [01:42:18,486] testLogger@instanceLoggerITD: Test customLogger ITD instance org.apache.log4j.Logger@1e8a1f6 <\/p>\n<p>INFO  [01:42:18,486] com.test.TestInjectedLoggerITD@instanceLoggerITD: Test Logger ITD instance org.apache.log4j.Logger@<strong>1ab28fe <\/strong><br \/>\nINFO  [01:42:18,486] testLogger@instanceLoggerITD: Test customLogger ITD instance org.apache.log4j.Logger@1e8a1f6 <\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we discuss about another ApectJ advanced feature: inter-type declaration (ITD), or more commonly called member introduction. In essence, this feature lets you &#8220;inject&#8221; new fields or methods into an existing class using an aspect. With ITD you&#8230;<br \/><a class=\"read-more-button\" href=\"https:\/\/www.doanduyhai.com\/blog\/?p=416\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,5],"tags":[33,38],"_links":{"self":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/416"}],"collection":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=416"}],"version-history":[{"count":0,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/416\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=416"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=416"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}