AOP (Aspect Oriented Programming) - 5
AOP (Aspect Oriented Programming) - 5
Dependency Injection
1 Introduction
A key feature of the new generation of component frameworks like the Spring
framework [10] is dependency injection [6]. It is a programming technique for re-
ducing the dependency among components and thereby improving the reusabil-
ity of the components. If a component includes sub-components, reusing only
that component as is independently of those sub-components is often diffi-
cult. For example, if one of those sub-components is for accessing a particular
database, it might need to be replaced with another sub-component for a dif-
ferent database when the component is reused. The original program of that
component must be edited for the reuse since it includes the code for instantiat-
ing the sub-component. The idea of dependency injection is to move the code for
instantiating sub-components from the program of a component to a component
framework, which makes instances of sub-components specified by a separate
configuration file (usually an XML file) and automatically stores them in the
component.
Dependency injection is a good idea for reducing inter-component depen-
dency. However, since existing component frameworks with dependency injec-
tion are implemented with a normal language, mostly in Java, the independence
and reusability of components are unsatisfactory. For example, the programs of
components depend on a particular component framework and thus they must
be modified when they are reused with a different framework.
A.P. Black (Ed.): ECOOP 2005, LNCS 3586, pp. 121–143, 2005.
c Springer-Verlag Berlin Heidelberg 2005
122 S. Chiba and R. Ishikawa
㪤㫐㪪㪼㫉㫍㫀㪺㪼 㪤㫐㪙㫌㫊㫀㫅㪼㫊㫊㪫㪸㫊㫂
㪂㫊㪼㫉㫍㪼㩿㪀 㪂㪻㫆㪤㫐㪡㫆㪹㩿㪀
㪓㪓㫀㫅㫋㪼㫉㪽㪸㪺㪼㪕㪕
㪛㪸㫋㪸㪹㪸㫊㪼
㪂㫈㫌㪼㫉㫐㩿㪪㫋㫉㫀㫅㪾㪀㩷㪑㩷㪦㪹㫁㪼㪺㫋
㪧㫆㫊㫋㪾㫉㪼㪪㪨㪣 㪤㫐㪪㪨㪣
㪂㫈㫌㪼㫉㫐㩿㪪㫋㫉㫀㫅㪾㪀㩷㪑㩷㪦㪹㫁㪼㪺㫋 㪂㫈㫌㪼㫉㫐㩿㪪㫋㫉㫀㫅㪾㪀㩷㪑㩷㪦㪹㫁㪼㪺㫋
framework constructs a MyBusinessTask object for injecting it into the task field
in a MyService object, the constructor of MyService does not have to explicitly
call the getBean method on factory. We can write the program of MyService with-
out referring to XmlBeanFactory. However, this solution requires all components
to be constructed through an XmlBeanFactory object. For example, MyService
might be always reused with MyBusinessTask since these two components are
tightly coupled. If so, dependency injection is not necessary for MyService but we
must write a configuration file for MyService and construct the MyBusinessTask
component through an XmlBeanFactory object. This programming convention is
somewhat awkward.
If this class is compiled with the aspect, the construction of MyBusinessTask is in-
tercepted and then a MySQL object is assigned to the db field in MyBusinessTask.
126 S. Chiba and R. Ishikawa
3 GluonJ
This section presents GluonJ, which is our new aspect-oriented programming
framework for Java. The design of GluonJ is based on the pointcut-advice archi-
tecture of AspectJ. However, this architecture has been restructured for GluonJ
to provide a simpler programming model for reducing inter-component depen-
dency.
GluonJ separates aspect bindings from aspect implementations. Aspect im-
plementations are regular Java objects, which implement a crosscutting concern.
They corresponds to an aspect instance in AspectJ. Aspect binding is the glue
code described in XML. It specifies how an aspect implementation is associated
with aspect targets, which the aspect implementation cuts across, at specified
join points. The aspect binding includes not only pointcuts but also code frag-
ments written in Java. These code fragments explicitly specify which aspect im-
plementation is associated with the aspect targets. If program execution reaches
a join point specified by a pointcut, then the code fragment is executed. It can
explicitly construct an aspect implementation and call a method on that aspect
implementation to execute a crosscutting concern. Since GluonJ was designed
for reducing inter-component dependency, GluonJ lets developers to describe
128 S. Chiba and R. Ishikawa
Fig. 2. The aspect of GluonJ is glue, which connects two components. Unlike the
aspect of AspectJ, the aspect of GluonJ is not part of the Logger component or the
MyBusinessTask component
the code fragments in the aspect binding to explicitly express various relations
between aspect targets and aspect implementations.
Logger is a class for the logging concern. Unlike AspectJ, GluonJ uses a regular
Java object as an aspect implementation, which is a component implementing a
crosscutting concern such as the logging concern.
In GluonJ, an aspect means the aspect binding written in XML, for example,
for describing the dependency between a Logger object and other objects. It glues
a Logger object to the objects that must produce log messages (Figure 2). The
aspect does not include an aspect implementation, which is the Logger class. For
example, the following aspect specifies that a log message is printed just after a
method in MyBusinessTask is executed:
<aspect>
<injection>
Logger MyBusinessTask.aspect = new Logger();
</injection>
<advice>
<pointcut>
Aspect-Oriented Programming Beyond Dependency Injection 129
execution(* MyBusinessTask.*(..))
</pointcut>
<after>
Logger.aspectOf(this).log();
</after>
</advice>
</aspect>
This aspect makes it possible to keep the two components MyBusinessTask and
Logger loosely coupled with low dependency on each other. The GluonJ compiler
automatically transforms the program of MyBusinessTask according to this as-
pect at compilation time. Thus, we can change the behavior of MyBusinessTask
without manually modifying the program of MyBusinessTask.
The statement surrounded with the injection tag specifies a connection be-
tween a MyBusinessTask object and a Logger object. It means that, when a
MyBusinessTask is constructed, a Logger object is also constructed and then as-
sociated with that MyBusinessTask object. The syntax of this statement is the
same as the intertype field declaration in AspectJ except aspect is not a field
name but a special keyword.
The elements surrounded with the advice tag are pointcut and after advice.
The pointcut is surrounded with the pointcut tag. It is the almost same language
element as AspectJ’s pointcut except the syntax. In the aspect shown above, the
pointcut picks out as join points method execution on MyBusinessTask objects.
The code snippet surrounded with the after tag is an advice body, which is
executed just after a thread of control reaches the execution point specified by
the pointcut. The code snippet is written in regular Java except that a special
form aspectOf is available in that code snippet. In the aspect shown above,
Logger.aspectOf(this) is used to obtain the Logger object associated with the
MyBusinessTask object referred to by this. aspectOf is a special form that is used
in the following form:
<class name>.aspectOf(<object>)
This special form is used to obtain an object associated with another object by
the injection tag. It returns the object that is of the <class name> type and is
associated with the given <object>.
The advice body, which is the code snippet surrounded with the after tag,
is executed in the context of the join point picked out by a pointcut. In the
case of our example, the advice body is executed on an MyBusinessTask object
since the join points picked out are the execution points when a method is
executed on that object. Therefore, this appearing in the advice body refers to
that MyBusinessTask object although it refers to an aspect instance in AspectJ. If
needed, the advice body can access private fields and methods in MyBusinessTask.
This is not allowed in AspectJ unless the aspect is privileged. On the other hand,
the advice body in GluonJ cannot access private fields or methods in Logger.
The visibility scope is determined by the execution context of the advice body.
In AspectJ, it is an instance of the aspect while it is the same context as the
join point in GluonJ.
130 S. Chiba and R. Ishikawa
<injection>
Logger MyBusinessTask.link = new Logger();
</injection>
This adds a new field named link to the MyBusinessTask class and it initializes
the value of that field so that it refers to a Logger object. The type of that field
is Logger. However, this may cause naming conflict if another aspect adds a link
field to the MyBusinessTask class.
If a special keyword aspect is specified as the name of the added field, this
field becomes an anonymous field, that is, a field that has no name. An anony-
mous field can be accessed only through the special form aspectOf. For example,
Logger.aspectOf(p) represents the anonymous field that is Logger type and be-
longs to the object p. We do not have to manually choose a unique field name
for avoiding naming conflict.
There is also another rule with respect to the name of a newly added field.
If the specified field name is the same as an already existing field in the same
class, a new field is never added to the class. The initial value specified in the
block surrounded with injection is assigned to that existing field with the same
name.
This rule allows us to describe dependency injection with a simple aspect.
For example, the example shown in the previous section can be described with
the following aspect:
<aspect>
<injection>
Database MyBusinessTask.db = new MySQL();
</injection>
</aspect>
Aspect-Oriented Programming Beyond Dependency Injection 131
This aspect specifies that a MySQL object is constructed and assigned to the
db field in MyBusinessTask when an MyBusinessTask object is constructed. Since
the db field already exists, no new field is added to MyBusinessTask. The as-
pect does not have to include a pointcut for picking out the construction of a
MyBusinessTask object.
Although the block surrounded with the injection tag is similar to the inter-
type field declaration of AspectJ, it is not the same language element as the
intertype field declaration. The added fields in GluonJ are private fields only ac-
cessible in the class to which those fields are added. On the other hand, private
fields added by intertype field declarations of AspectJ are not accessible from the
class to which those fields are added. They are only accessible from the aspect
(implementation) that declares those fields.
Injection Tag: In a block surrounded with the injection tag, an anonymous field
can be declared. For example, the following declaration adds a new anonymous
field to the MyBusinessTask class:
<injection>
Logger MyBusinessTask.aspect = new Logger(this);
</injection>
The initial value of the field is computed and assigned right after an instance of
MyBusinessTask is constructed. The expression computing the initial value can
be any Java expression. For example, it can include the this variable, which refers
to that MyBusinessTask object in the example above.
If the declaration above starts with static, then a static field is added to the
class. The initial value is assigned when the other static fields are initialized.
The field added by the declaration above is accessible only in the aspect.
To obtain the value of the field, the special form aspectOf must be called. For
example, Logger.aspectOf(t) returns the Logger object stored in the anonymous
Aspect-Oriented Programming Beyond Dependency Injection 133
aspectOf returns the Logger object stored in thisCflow. thisCflow refers to the
Cflow object representing the current control flow.
An anonymous field can be used to associate a group of objects with another
object. This mechanism provides similar functionality to the association aspects
[17]. For example,
<injection>
Logger MyBusinessTask.aspect(Session) = new Logger(this, args);
</injection>
This declaration associates multiple Logger objects with one MyBusinessTask. this
and args are special variables. These Logger objects are identified by a Session
object given as a key. The type of the key is specified in the parentheses following
aspect. Multiple keys can be specified. The associated objects are obtained by
aspectOf. For example,
Logger.aspectOf(task, session).log();
This statement calls the log method on the Logger object associated with a com-
bination of task and session. aspectOf takes two parameters: the first parameter is
a MyBusinessTask object and the second one is a Session object. aspectOf returns
an object associated with the combination of these objects passed as parame-
ters. If any object has not been associated with the given combination, aspectOf
constructs an object and associates it with that combination. In other words, an
134 S. Chiba and R. Ishikawa
associated object is never constructed until aspectOf is called. In the case of the
example above, a Logger object is constructed with parameters this and args. this
refers to the first parameter to AspectOf (i.e. the MyBusinessTask object) and
args refers to an array of Object. The elements of this array are the parameters
to aspectOf except the first one. In this example, args is an array containing only
the Session object as an element.
Advice Tag: A block surrounded with the advice tag consists of a pointcut
and an advice body. The pointcut is specified by the pointcut tag. The syntax
of the pointcut language was borrowed from AspectJ although the current im-
plementation of GluonJ does not support the if and adviceexecution pointcut
designators. Although && and || must be escaped, AND and OR can be used
as substitution. The current implementation of GluonJ has neither supported a
named pointcut. A pointcut parameter is defined by using the param tag. For
example, the following aspect uses an int parameter i as a pointcut parameter.
It is available in the pointcut and the advice body.
<advice>
<param><name>i</name><type>int</type></param>
<pointcut>
execution(* MyBusinessTask.*(..)) AND args(i)
</pointcut>
<after>
Logger.aspectOf(this).log(i);
</after>
</advice>
4 Comparison to AspectJ
Although GluonJ has borrowed a number of ideas from AspectJ, there are a
few significant differences between them. The first one is the visibility rule. The
Aspect-Oriented Programming Beyond Dependency Injection 135
advice body in GluonJ can access private members of the aspect target since it is
glue code. On the other hand, the advice body in AspectJ cannot access except
the members added by the intertype declarations. This is because the advice
body in AspectJ belongs to the aspect implementation.
Another difference is how to specify which aspect implementation is associ-
ated with an aspect target. This section illustrates comparison between GluonJ
and AspectJ with respect to this issue. Although GluonJ is similar to JBoss AOP
and AspectWerkz rather than AspectJ, we compare GluonJ to AspectJ since the
readers would be more familiar to AspectJ. In fact, AspectJ, JBoss AOP, and
AspectWerkz are based on the same idea with respect to the association of as-
pect implementations. Note that, like GluonJ, JBoss AOP and AspectWerkz
separate aspect bindings in XML from aspect implementation in Java. Although
their aspect implementations are Java objects, they are implicitly constructed
and associated as in AspectJ. On the other hand, an aspect implementation in
GluonJ is explicitly constructed and associated.
4.1 Example
To illustrate that explicit association of aspect implementations in GluonJ en-
ables a better expression of inter-component dependency than AspectJ, we present
an implementation of simple caching mechanism in AspectJ and GluonJ. If a
method always returns the same value when it is called with the same arguments,
the returned value should be cached to improve the execution performance. Sup-
pose that we would like to cache the result of the doExpensiveJob method in the
following class:
136 S. Chiba and R. Ishikawa
Note that the returned value from doExpensiveJob depends only on the parameter
s and the sessionId field. Thus we share cache memory among MyTask objects
with the same session id.
We below see how GluonJ and AspectJ express the dependency between
MyTask and the caching component. The goal is to implement the caching com-
ponent to be independent of MyTask and naturally connect the two components
by an aspect.
4.2 GluonJ
We first show the implementation in GluonJ (Figure 3). The following is the
class for a caching component:
public class Cache {
private HashMap cache = new HashMap();
public Object getValue(JoinPoint thisJoinPoint, Object arg) {
Object result = cache.get(arg);
if (result == null) {
try {
result = thisJoinPoint.proceed();
cache.put(arg, result);
} catch (Throwable e) {}
}
return result;
}
// create a cache for each session.
private static HashMap cacheMap = new HashMap();
private static Cache factory(int sessionId) {
Integer id = new Integer(sessionId);
Cache c = (Cache)cacheMap.get(id);
if (c == null) {
c = new Cache();
cacheMap.put(id, c);
}
return c;
}
}
This component holds a hash table for caching the value returned from a method.
factory is a factory method for constructing a Cache object for each session.
The Cache component is associated with a MyTask object. This association
is described in the following aspect:
<aspect>
<injection>
Cache MyTask.aspect = Cache.factory(this.sessionId);
</injection>
<advice>
<param><name>s</name> <type>String</type></param>
<pointcut>
execution(String MyTask.doExpensiveJob(..)) AND args(s)
</pointcut>
<around>
return (String)Cache.aspectOf(this)
.getValue(thisJoinPoint, s);
</around>
</advice>
</aspect>
This aspect adds an anonymous field to MyTask. The value of this field is a
Cache object for the session that the MyTask object belongs to. Then, if the
doExpensiveJob method is executed, this aspect calls the getValue method on
the associated Cache object.
Note that a Cache object is explicitly constructed in the aspect by calling a
factory method. It is thereby associated with multiple MyTask objects belonging
to the same session. The resulting object graph in Figure 3 naturally represents
that the caching concern is per-session cache.
Note that the hash table is stored in the cache field of the aspect instance. This
aspect does not include intertype declaration. The cache field is a member of
this aspect itself.
This implementation is simpler than the previous one since an instance of
CacheAspect2 manages only one hash table stored in a field of that instance.
CacheAspect2 does not have to access a field in MyTask. However, this implemen-
tation produces redundant aspect instances. The role of each aspect instance is
merely a simple bridge between a MyTask object and a hash table. It has nothing
elaborate. This is not appropriate from the viewpoint of either program design
or efficiency.
Note that, in this implementation, both the caching component and the de-
pendency description (with pointcuts and advice) are also tangled in CacheA-
spect2. However, separating the dependency description from the program of the
caching component is not difficult if abstract pointcuts are used. We can define
an aspect only for the caching mechanism and then define another aspect that
extends the former aspect and implements the abstract pointcut for describing
the dependency. The perthis modifier must be defined in the latter aspect.
This would be the best implementation among the three AspectJ-based ones.
The caching aspect is separated and independent of MyTask. No redundant as-
pect instance is produced. However, it is never highly efficient to call the factory
method whenever the doExpensiveJob method is executed. Furthermore, this cen-
tralized design of caching mechanism is implementation-oriented. It would not
be the design easily derived after the modeling phase. The easily derived design
would be something like Figure 3 achieved by GluonJ. Figure 6 shown here would
be the design that we could obtain by modifying that easily derived design to
be suitable for implementation in a particular language.
Note that, in the implementation shown above, the dependency description
(with pointcuts and advice) is also tangled with the caching component. How-
ever, separating the dependency description from the program of the caching
component is possible by using abstract pointcuts.
5 Related Work
There are a number of aspect-oriented languages and frameworks that separate
aspect binding and aspect implementation. Like GluonJ, JBoss AOP [9] and
AspectWerkz [1] uses XML for describing aspect binding while Aspectual Com-
ponents [13], Caesar [14] and JAsCo [19] uses extended language constructs.
JAC [16] uses a programming framework in regular Java. Even AspectJ pro-
vides abstract aspects for this separation [8]. However, these systems allow only
implicit association of an aspect implementation and hence they have a problem
discussed in this paper. An aspect implementation is automatically constructed
and implicitly associated with the aspect target in the specified scheme such
as issingleton and perthis of AspectJ. Although JBoss AOP provides customiza-
tion interface in Java for extending the behavior of perthis, it complicates the
programming model.
The dynamic weaving mechanism of Caesar [14] allows associating an as-
pect implementation at runtime when the developers specify. It provides better
flexibility but an aspect implementation is still automatically constructed and
implicitly associated with the aspect target.
Association aspect [17] allows implementing a crosscutting concern by an
explicitly constructed instance of an aspect. It is an extension to AspectJ and
it is a language construct focusing on associating an aspect instance to a tuple
of objects. GluonJ can be regarded as a framework generalizing the idea of
association aspect and applying it to dependency reduction among components.
The implicit association of an aspect implementation (and an aspect instance
in AspectJ) might be the ghost of the metaobject protocol [11], which is one of
the origins of aspect-orientated programming. Although this design is not a
problem if an aspect crosscuts only a single other concern, it should be revised
142 S. Chiba and R. Ishikawa
6 Conclusion
Reducing inter-component dependency is the goal of dependency injection but
aspect-oriented programming can give a better solution to this goal. However,
existing aspect-oriented programming systems have a problem. They can express
only limited kinds of dependency relation since they implicitly associate an as-
pect implementation with an aspect target. The developers cannot fully control
this relation.
To address this problem, this paper proposed GluonJ, which is our aspect-
oriented framework for Java. A unique feature of GluonJ is that an aspect im-
plementation is explicitly associated with aspect targets. An aspect in GluonJ
consists of pointcuts and glue code written in Java. This glue code explicitly
constructs an aspect implementation and associates it with appropriate aspect
targets. The aspect implementation in GluonJ is a regular Java object.
We have implemented a prototype of GluonJ as a bytecode translator built
on top of Javassist [2]. It supports most pointcut designators of AspectJ except
cflow, which will be implemented in near future.
References
1. Boner, J., Vasseur, A.: AspectWerkz 1.0. http://aspectwerkz.codehaus.org/
(2002)
2. Chiba, S.: Load-time structural reflection in Java. In: ECOOP 2000. LNCS 1850,
Springer-Verlag (2000) 313–336
3. Chiba, S., Masuda, T.: Designing an extensible distributed language with a meta-
level architecture. In: Proc. of the 7th European Conference on Object-Oriented
Programming. LNCS 707, Springer-Verlag (1993) 482–501
Aspect-Oriented Programming Beyond Dependency Injection 143
4. Cohen, T., Gil, J.Y.: AspectJ2EE = AOP + J2EE : Towards an aspect based,
programmable and extensible middleware framework. In: Proceedings of the Euro-
pean Conference on Object-Oriented Programming. Number 3086 in LNCS (2004)
219–243
5. Eichberg, M., Mezini, M.: Alice: Modularization of middleware using aspect-
oriented programming. In: Software Engineering and Middleware (SEM) 2004.
(2004)
6. Fowler, M.: Inversion of control containers and the dependency injection pattern.
http://www.martinfowler.com/articles/injection.html (2004)
7. Golm, M., Kleinöder, J.: Jumping to the meta level, behavioral reflection can be
fast and flexible. In: Proc. of Reflection ’99. LNCS 1616, Springer (1999) 22–39
8. Hannemann, J., Kiczales, G.: Design pattern implementation in java and aspectj.
In: Proc. of ACM Conf. on Object-Oriented Programming Systems, Languages,
and Applications. (2002) 161–173
9. JBoss Inc.: JBoss AOP 1.0.0 final. http://www.jboss.org/ (2004)
10. Johnson, R., Hoeller, J.: Expert One-on-One J2EE Development without EJB.
Wrox (2004)
11. Kiczales, G., des Rivières, J., Bobrow, D.G.: The Art of the Metaobject Protocol.
The MIT Press (1991)
12. Kiczales, G., Hilsdale, E., Hugunin, J., Kersten, M., Palm, J., Griswold, W.G.: An
overview of AspectJ. In: ECOOP 2001 – Object-Oriented Programming. LNCS
2072, Springer (2001) 327–353
13. Lieberherr, K., Lorenz, D., Mezini, M.: Programming with Aspectual Components.
Technical Report NU-CCS-99-01, College of Computer Science, Northeastern Uni-
versity, Boston, MA (1999)
14. Mezini, M., Ostermann, K.: Conquering aspects with caesar. In: Proc. of Int’l
Conf. on Aspect-Oriented Software Development (AOSD’03), ACM Press (2003)
90–99
15. Orleans, D.: Incremental programming with extensible decisions. In: AOSD ’02:
Proceedings of the 1st international conference on Aspect-oriented software devel-
opment, ACM Press (2002) 56–64
16. Pawlak, R., Seinturier, L., Duchien, L., Florin, G.: Jac: A flexible solution for
aspect-oriented programming in java. In: Metalevel Architectures and Separation
of Crosscutting Concerns (Reflection 2001). LNCS 2192, Springer (2001) 1–24
17. Sakurai, K., Masuhara, H., Ubayashi, N., Matsuura, S., Kimoya, S.: Association
aspects. In: Aspect-Oriented Software Development. (2004) 16–25
18. Smith, B.C.: Reflection and semantics in Lisp. In: Proc. of ACM Symp. on Prin-
ciples of Programming Languages. (1984) 23–35
19. Suvée, D., Vanderperren, W., Jonckers, V.: Jasco: An aspect-oriented approach
tailored for component based software development. In: Proc. of Int’l Conf. on
Aspect-Oriented Software Development (AOSD’03), ACM Press (2003) 21–29
20. Welch, I., Stroud, R.: From dalang to kava — the evolution of a reflective java
extension. In: Proc. of Reflection ’99. LNCS 1616, Springer (1999) 2–21