the state of aop · 2013. 3. 21. · core aop concepts join point an identifiable point in the...
TRANSCRIPT
September 2006
The State of AOP
Ramnivas Laddad
Principal, Interface21
Author, AspectJ in Action
September 2006
Speaker introduction
� Principal at Interface21� Specializing in aspect-oriented programming and enterprise Java
� Author of books and articles� AspectJ in Action: Practical Aspect-Oriented Programming
� Several articles on IBM developerWorks,TheServerSide, JavaWorld and other publications
� Speaker at many professional conferences� No Fluff Just Stuff, JavaOne, JavaPolis, Software Development, EclipseCon, O’Reilly OSCON etc.
� Active involvement in AspectJ since its early form
September 2006
Agenda
An introduction to AOP
New and cool in AspectJ
Spring AOP
Spring AspectJ integration
Demos
Q&A
September 2006
Agenda
An introduction to AOP
New and cool in AspectJ
Spring AOP
Spring AspectJ integration
Demos
Q&A
September 2006
In the beginning…
� Class ATM � Class Account
package banking;
public class ATM {
private String _id;
private String _address;
private transient ATMCard _currentATMCard;
private transient Account _currentAccount;
public ATM(String id, String address) {
_id = id;
_address = address;
}
public String getID() {
return _id;
}
public String getAddress() {
return _address;
}
public void setCurrentATMCard(ATMCard currentATMCard) {
_currentATMCard = currentATMCard;
}
public void setCurrentAccount(Account currentAccount) {
_currentAccount = currentAccount;
}
public void credit( float amount) {
_currentATMCard.getBankLiaison()
.credit(_currentAccount, amount);
}
public void debit( float amount) throws InsufficientBalanceException {
_currentATMCard.getBankLiaison()
.debit(_currentAccount, amount);
}
public float getBalance() {
return _currentATMCard.getBankLiaison()
.getBalance(_currentAccount);
}
}
package banking;
public class Account {private int _accountNumber;private float _balance;
public Account( int accountNumber) { _accountNumber = accountNumber;
}
public int getAccountNumber() {return _accountNumber;
}
public void credit( float amount) {_balance = _balance + amount;
}
public void debit( float amount)throws InsufficientBalanceException {if (_balance < amount) {
throw new InsufficientBalanceException("Total balance not sufficient" );
} else {_balance = _balance - amount;
}}
public float getBalance() {return _balance;
}
public String toString() {return "Account: " + _accountNumber;
}
}
September 2006
Let’s add logging…
� Class ATM � Class Account
package banking;
import java.util.logging.*;
public class ATM {
...
private static Logger _logger= Logger.getLogger( "banking" );
...
public void credit( float amount) {_logger.logp(Level.INFO,
"ATM" , "credit" , "Entering" );
_currentATMCard.getBankLiaison()
.credit(_currentAccount, amount);
}
public void debit( float amount)throws InsufficientBalanceException {_logger.logp(Level.INFO,
"ATM" , "debit" , "Entering" );
_currentATMCard.getBankLiaison()
.debit(_currentAccount, amount);
}
...
}
package banking;
import java.util.logging.*;
public class Account {
...
private static Logger _logger= Logger.getLogger( "banking" );
...
public void credit( float amount) {_logger.logp(Level.INFO,
"Account" , "credit" , "Entering" );_balance = _balance + amount;
}
public void debit( float amount)throws InsufficientBalanceException {_logger.logp(Level.INFO,
"Account" , "debit" , "Entering" );if (_balance < amount) {
throw new InsufficientBalanceException("Total balance not sufficient" );
} else {_balance = _balance - amount;
}}
...
}
September 2006
Let’s add logging…
� Class ATM � Class Account
package banking;
import java.util.logging.*;
public class ATM {
...
private static Logger _logger= Logger.getLogger( "banking" );
...
public void credit( float amount) {_logger.logp(Level.INFO,
"ATM" , "credit" , "Entering" );
_currentATMCard.getBankLiaison()
.credit(_currentAccount, amount);
}
public void debit( float amount)throws InsufficientBalanceException {_logger.logp(Level.INFO,
"ATM" , "debit" , "Entering" );
_currentATMCard.getBankLiaison()
.debit(_currentAccount, amount);
}
...
}
package banking;
import java.util.logging.*;
public class Account {
...
private static Logger _logger= Logger.getLogger( "banking" );
...
public void credit( float amount) {_logger.logp(Level.INFO,
"Account" , "credit" , "Entering" );_balance = _balance + amount;
}
public void debit( float amount)throws InsufficientBalanceException {_logger.logp(Level.INFO,
"Account" , "debit" , "Entering" );if (_balance < amount) {
throw new InsufficientBalanceException("Total balance not sufficient" );
} else {_balance = _balance - amount;
}}
...
}
September 2006
…and access control
� Class ATM � Class Account
package banking;
import java.security.*;
import javax.security.auth.*;
import java.util.logging.*;
public class ATM {
...
private Subject _atmSubject;
private static Logger _logger = Logger.getLogger( "banking" );
...
public void credit( final float amount) {
_logger.logp(Level.INFO, "ATM" , "credit" , "Entering" );PrivilegedAction worker
= new PrivilegedAction() {public Object run() {
_currentATMCard.getBankLiaison().credit(_currentAcc ount, amount);
return null ;}};
Subject.doAsPrivileged(_atmSubject, worker, null );}
public void debit( final float amount) throws InsufficientBalanceException {_logger.logp(Level.INFO, "ATM" , "debit" , "Entering" );
PrivilegedExceptionAction worker= new PrivilegedExceptionAction() {
public Object run() throws Exception {_currentATMCard.getBankLiaison().debit(_currentAcco unt, amount);return null ;
}};
try {Subject.doAsPrivileged(_atmSubject, worker, null );
} catch (PrivilegedActionException ex) {Throwable cause = ex.getCause();
if (cause instanceof InsufficientBalanceException) {throw (InsufficientBalanceException)ex.getCause();
}}
}
...
}
package banking;
import java.util.logging.*;
import java.security.AccessController;
public class Account {
...
private static Logger _logger = Logger.getLogger( "banking" );
...
public void credit( float amount) {
AccessController.checkPermission(
new BankingPermission( "accountOperation" ));
_logger.logp(Level.INFO,
"Account" , "credit" , "Entering" );
_balance = _balance + amount;
}
public void debit( float amount) throws InsufficientBalanceException {
AccessController.checkPermission(
new BankingPermission( "accountOperation" ));
_logger.logp(Level.INFO,
"Account" , "debit" , "Entering" );
if (_balance < amount) {
throw new InsufficientBalanceException(
"Total balance not sufficient" );
} else {
_balance = _balance - amount;
}
}
...
}
September 2006
…and access control
� Class ATM � Class Account
package banking;
import java.security.*;import javax.security.auth.*;
import java.util.logging.*;
public class ATM {...
private Subject _atmSubject;
private static Logger _logger = Logger.getLogger( "banking" );
...
public void credit( final float amount) {_logger.logp(Level.INFO, "ATM" , "credit" , "Entering" );PrivilegedAction worker
= new PrivilegedAction() {public Object run() {
_currentATMCard.getBankLiaison().credit(_currentAcc ount, amount);return null ;
}};Subject.doAsPrivileged(_atmSubject, worker, null );
}
public void debit( final float amount) throws InsufficientBalanceException {_logger.logp(Level.INFO, "ATM" , "debit" , "Entering" );
PrivilegedExceptionAction worker
= new PrivilegedExceptionAction() {public Object run() throws Exception {
_currentATMCard.getBankLiaison().debit(_currentAcco unt, amount);return null ;
}};
try {Subject.doAsPrivileged(_atmSubject, worker, null );
} catch (PrivilegedActionException ex) {
Throwable cause = ex.getCause();if (cause instanceof InsufficientBalanceException) {
throw (InsufficientBalanceException)ex.getCause();}
}
}
...
}
package banking;
import java.util.logging.*;
import java.security.AccessController;
public class Account {
...
private static Logger _logger = Logger.getLogger( "banking" );
...
public void credit( float amount) {
AccessController.checkPermission(
new BankingPermission( "accountOperation" ));
_logger.logp(Level.INFO,
"Account" , "credit" , "Entering" );
_balance = _balance + amount;
}
public void debit( float amount) throws InsufficientBalanceException {
AccessController.checkPermission(
new BankingPermission( "accountOperation" ));
_logger.logp(Level.INFO,
"Account" , "debit" , "Entering" );
if (_balance < amount) {
throw new InsufficientBalanceException(
"Total balance not sufficient" );
} else {
_balance = _balance - amount;
}
}
...
}
September 2006
…and access control
� Class ATM � Class Account
package banking;
import java.security.*;import javax.security.auth.*;
import java.util.logging.*;
public class ATM {...
private Subject _atmSubject;
private static Logger _logger = Logger.getLogger( "banking" );
...
public void credit( final float amount) {_logger.logp(Level.INFO, "ATM" , "credit" , "Entering" );PrivilegedAction worker
= new PrivilegedAction() {public Object run() {
_currentATMCard.getBankLiaison().credit(_currentAcc ount, amount);return null ;
}};Subject.doAsPrivileged(_atmSubject, worker, null );
}
public void debit( final float amount) throws InsufficientBalanceException {_logger.logp(Level.INFO, "ATM" , "debit" , "Entering" );
PrivilegedExceptionAction worker
= new PrivilegedExceptionAction() {public Object run() throws Exception {
_currentATMCard.getBankLiaison().debit(_currentAcco unt, amount);return null ;
}};
try {Subject.doAsPrivileged(_atmSubject, worker, null );
} catch (PrivilegedActionException ex) {
Throwable cause = ex.getCause();if (cause instanceof InsufficientBalanceException) {
throw (InsufficientBalanceException)ex.getCause();}
}
}
...
}
package banking;
import java.util.logging.*;
import java.security.AccessController;
public class Account {
...
private static Logger _logger = Logger.getLogger( "banking" );
...
public void credit( float amount) {
AccessController.checkPermission(
new BankingPermission( "accountOperation" ));
_logger.logp(Level.INFO,
"Account" , "credit" , "Entering" );
_balance = _balance + amount;
}
public void debit( float amount) throws InsufficientBalanceException {
AccessController.checkPermission(
new BankingPermission( "accountOperation" ));
_logger.logp(Level.INFO,
"Account" , "debit" , "Entering" );
if (_balance < amount) {
throw new InsufficientBalanceException(
"Total balance not sufficient" );
} else {
_balance = _balance - amount;
}
}
...
}
September 2006
…and so it goes
� Transaction management
� Thread safety
� Caching
� Resource pooling
� Profiling
� Policy enforcement
� Monitoring
� Testing
� Statement generation
� Service level agreement enforcement
� Business rules
September 2006
A quick intro to AOP
� Crosscutting concerns
� Functionality whose implementation spans multiple modules
� Many examples: Logging and tracing, Transaction management, security, caching, error handling, business rules, performance monitoring…
� AOP
� A programming methodology to help with crosscutting concerns
September 2006
ATM Account
System Evolution: Conventional
Codescattering
…
…
Codetangling
September 2006
System Evolution: AOP based
Loggingaspect
Access controlaspect
ATM Account …
…
…
September 2006
Core AOP concepts
� Join point
� An identifiable point in the execution of a program.
� Central, distinguishing concept in AOP
� Pointcut
� Program construct that selects join points and collects context at those points.
� Advice
� Code to be executed at a join point that has been selected by a pointcut
� Introduction
� Additional data or method to existing types, implementing new interfaces
September 2006
Pointcut
� Selects join points and collects context at those points
� Example:pointcut release(Connection conn)
: call ( void Connection.close()) && target (conn);
pointcut accountCreation(Account account)
: execution (Account. new()) && this (account);
pointcut service()
: execution (* Remote+.*(..) throws RemoteException);
pointcut accountChangeFromATM(ATM atm, Account account)
: cflow (atmRequest(atm)) && accountChange(account);
September 2006
Dynamic crosscutting: Advice
� Code to be executed at a join point that has been selected by a pointcut
� Three kinds:
� Beforebefore () : call (* ATM.*(..)) {
...
}
� Afterafter (Account account) returning : accountOperation(account) {
...
}
� AroundObject around () : call (* Remote+.*(..) throws RemoteException) {
try {
... proceed (); ... Retry logic ...
} catch (...) {
}
}
September 2006
Static crosscutting
� Introduce new parent typesdeclare parents : banking..* implements Loggable;
� Introduce new memberspublic Logger Loggable._logger;
� Soften exceptionsdeclare soft : SQLException
: within (banking.model..*);
� Compile-time errors and warningdeclare error
: call (* Thread.*(..))&& within (javax.ejb.EnterpriseBean+)
: "Use of thread disallowed from EJBs" ;
September 2006
Agenda
An introduction to AOP
New and cool in AspectJ
Spring AOP
Spring AspectJ integration
Demos
Q&A
September 2006
AspectJ syntax and weaving
� Three syntaxes
� Language extension• New keywords
• Needs special compiler
� Metadata-based extension (@AspectJ)• Compilable using a plain Java compiler
� XML-based definition• Configuration modifications without recompiling
� AspectJ weaving options
� Compile-time weaver• Aspect and class source code � class files
� Binary weaver (“linker”)• Aspect and class source/binary files � class files
� Load-time weaver• Aspect and class binary files
� Weave class files when being loaded into VM
September 2006
AspectJ syntax guiding principles
� One language
� Multiple development styles
� One semantics
� One weaver
� Syntax and weaving model orthogonal
September 2006
Current AspectJ syntax
public aspect LoggingAspect {
private static Logger _logger = Logger.getLogger( "tracer" );
public pointcut loggedOperations()
: execution (* *.* (..));
before () : loggedOperations() {
Signature sig = thisJoinPointStaticPart .getSignature();
_logger.logp(Level.INFO,
sig.getDeclaringType().getName(),
sig.getName(), "Entering" );
}
}
September 2006
New @AspectJ syntax
@Aspect
public class LoggingAspect {
private static Logger _logger = Logger.getLogger( “tracer" );
@Pointcut(“ execution (* *.* (..))”)
public void loggedOperations() {}
@Before (“loggedOperations()”)
public void log(JoinPoint.StaticPart thisJoinPointStaticPart ) {
Signature sig = thisJoinPointStaticPart .getSignature();
_logger.logp(Level.INFO,
sig.getDeclaringType().getName(),
sig.getName(), "Entering" );
}
}
September 2006
XML syntax
� Base aspect expressed in traditional or @AspectJ syntax
public abstract aspect MonitoringAspect {
public abstract pointcut monitoredOps();
Object around () : monitoredOps() {
long startTime = System.nanoTime();
Object ret = proceed ();
long endTime = System.nanoTime();
monitorAgent.record( thisJoinPointStaticPart ,
endTime-startTime);
return ret;
}
...
}
September 2006
XML syntax: Defining concrete aspect<aspectj>
<aspects>
<concrete-aspect
name="com.aspectivity.monitoring.JDBCMonitoringAspe ct"
extends="com.aspectivity.monitoring.MonitoringAspec t">
<pointcut name="monitoredOps"
expression="call(* java.sql.*.*(..))"/>
</concrete-aspect>
...
</aspects>
...
</aspectj>
September 2006
Load-time weaving
� Weave while classes are being loaded
� No explicit compile-time or binary weaving needed
� Agents supported
� JVMTI-based• Application-server agnostic
• VMs supported− All 5.0+ VMs
java -javaagent:aspectjweaver.jar…− JRockit VM 1.3/1.4
java -Xmanagement:class=org.aspectj.weaver.loadtime.JRockitAgent…
� Classloader-based• Application-server specific
− Not available for all app servers
September 2006
LTW deployment: aop.xml
<aspectj>
<aspects>
<aspect name="com.aspectivity.security.FineGrainedS ecurity"/>
<aspect name="com.aspectivity.tracing.ExceptionTrac er"/>
<concrete-aspect
name="com.aspectivity.monitoring.JDBCMonitoringAspe ct"
extends="com.aspectivity.monitoring.MonitoringAspec t">
<pointcut name="monitoredOps"
expression="call(java.sql.*.*(..))"/>
</concrete-aspect>
</aspects>
<weaver>
<include within="com.interface21..*"/>
<exclude within="com.interface21.rss..*/>
</weaver>
</aspectj>
September 2006
Signature-based pointcut
� Utilize join point signatures
� Exploits inherent data associated with signature
� Wildcards select a wide range of join points
� Work well in many cases
� Logging and tracing
� Profiling
� Policy enforcement
� Caching and pooling
� Fault tolerance
� Thread safety
� Business rules
September 2006
Metadata based pointcuts
� Utilize join point metadata
� Often along with join point signature
� Needed in certain cases
� Transaction management
� Authentication
� Authorization
� Concurrency control
� …
September 2006
Selecting annotation based join points
� Execution of all secure operationspointcut secureOps()
: execution (@Secure * *.*(..));
� Access to all sensitive datapointcut sensitiveAccess()
: get (@Sensitive * *);
� Handler for non-catastrophic exceptionshandler (!@Catastrophic *)
September 2006
Collecting annotation instances
� Select join points with an @Tx annotationpointcut txOps() : @ annotation (Tx);
� Collect the @Tx annotationpointcut txOps(Tx tx) : @ annotation (tx);
� Match all join points with REQUIRED transactional attribute
pointcut txRequiredOps(Tx tx)
: @ annotation (tx)
&& if (tx.value() == TxType.REQUIRED);
September 2006
Annotation-specific pointcuts
� @annotation
� @this
� @target
� @args
� @within
� @withincode
September 2006
New AJDT features
� Improved debugging
� Setting breakpoints in advice or method
� Improved code completion
� And improving…
� Improved editing support
� Eager parsing enabled
� Improved visualization
� New views
� Crosscutting view
� Crosscutting comparison view
September 2006
Crosscutting view
� Replaces AspectJ-aware outline view
� Shows interaction between classes and aspects
� Updates incrementally
September 2006
Crosscutting comparison view
� Allows tracking effects of aspects during evolution
� Methods advised/not advised
� Static structure affected/not affected
September 2006
Layering violation enforcement
� Problem
� UI layer often directly use DAO layer contrary to architectural policies
� No automatic enforcement
� Solution
� One simple, reusable aspect to enforce the policies
• Just add to your build system
September 2006
Layering policy enforcement aspect
public aspect LayeringPolicyEnforcementAspect {
pointcut dataAccess()
: call (* com.mycompany.dao..*.*(..))
|| call (* org.hibernate..*.*(..))
|| call (* *..sql..*.*(..));
declare error : dataAccess()
&& within (com.mycompany.ui..*)
: "UI layer shouldn’t directly access data;
Use business layer instead" ;
}
September 2006
Cross repository contamination enforcement
public aspect RepositoryCrossContaminationEnforcement {
pointcut inAccountRoot()
within (com.mycompany.accounting..*);
declare error : set (com.mycompany.transactions..* *.*)
&& inAccountRoot();
: "Objects in the account root should not hold onto
objects from other roots";
}
September 2006
First failure data capture (FFDC)
� Problem:
� Exception at low level trickles through layers; however, original context is lost
� Solution:
� FFDC aspect logging the exception at the first failure site
September 2006
FFDC: Base aspect
public abstract aspect FFDC {
public abstract pointcut ffdcOp();
after () throwing (Exception ex) : ffdcOp() {
if (_logger.isLoggable(Level.WARNING)) {
Signature sig = thisJoinPointStaticPart .getSignature();
logFFDC(sig.getDeclaringType().getName(),
sig.getName(), ex,
thisJoinPoint .getThis(),
thisJoinPoint .getArgs());
}
}
public void logFFDC(String className, String methodName,
Exception ex, Object thiz, Object[] args) {
...
}
}
September 2006
FFDC: Derived aspect
public aspect BlogFFDC extends FFDC {
public pointcut ffdcOp()
: execution (* com.mycompany..*.*(..)
throws RemoteException)
|| execution (* com.mycompany..dao.*.*(..));
}
September 2006
Authorization
� Problem:
� Many methods in the system needs to check for authorized access
� Solution:
� An aspect using JAAS as the underlying authorization mechanism
September 2006
Authorization: Reusable base aspect
public abstract aspect AbstractAuthAspect {
public abstract pointcut authorizedOperations();
public abstract Permission getPermission(
JoinPoint.StaticPart jpsp);
before () : authorizedOperations() {
AccessController.checkPermission(
getPermission( thisJoinPointStaticPart ));
}
}
September 2006
Authorization: Derived aspect
public aspect BankingAuthAspect extends AbstractAuthAspect {
public pointcut authorizedOperations ()
: execution ( public * banking..Account.*(..));
public Permission getPermission(JoinPoint.StaticPart jpsp) {
return new BankingPermission(jpsp.getSignature().getName());
}
}
September 2006
Mix-in implementation
� Problem:
� Boilerplate implementation of an implementation
� Solution:
� Provide the default implementation using static crosscutting
September 2006
Interface needing boilerplate code
public interface ServiceCenter {
public String getId();
public void setId(String id);
public String getAddress();
public void setAddress(String address);
}
September 2006
Interface with mixin implementation
public interface ServiceCenterMixin extends ServiceCenter {
static aspect IMPL {
private String ServiceCenterMixin.id;
private String ServiceCenterMixin.address;
public String ServiceCenterMixin.getId() {
return id;
}
public void ServiceCenterMixin.setId(String id) {
this .id = id;
}
public String ServiceCenterMixin.getAddress() {
return address;
}
public void ServiceCenterMixin.setAddress(String address) {
this. address = address;
}
}
}
September 2006
Interface implementations
public class ATM extends Teller
implements ServiceCenterMixin {
... No set/getId(), set/getAddress()
... No id, address
}
public class BrickAndMortar extends Teller
implements ServiceCenterMixin {
... No set/getId(), set/getAddress()
... No id, address
}
September 2006
Injecting dependencies using Aspect
� Limitations of Spring’s “traditional” DI
� Injection limited to beans created through configuration
� Not sufficient for objects created thru other mechanisms: Hibernate, JDO, fine grained objects
� Prevents richer domain models prescribed by domain-driven design (DDD)
� Solution: Use aspects to inject dependencies
September 2006
Dependency declaration:Based on template id
@Configurable ( "emailerClient" )
public class Order {
private Emailer emailer ;
public void process() {
...
emailer.send(...)
}
public void setEmailer(Emailer emailer) {
this. emailer = emailer;
}
}
September 2006
Dependency configuration:Based on template id
<beans...>
</beans>
<aop:spring-configured />
<bean id ="smtpEmailer" .../>
<bean id ="emailerClient" scope ="prototype" >
<property name="emailer" ref ="smtpEmailer" />
</ bean >
September 2006
Dependency declaration:Based on template class
@Configurable
public class Order {
private Emailer emailer ;
public void process() {
...
emailer.send(...)
}
public void setEmailer(Emailer emailer) {
this. emailer = emailer;
}
}
September 2006
Dependency configuration: Based on template class
<beans...>
</beans>
<aop:spring-configured />
<bean id ="smtpEmailer" .../>
<bean class ="example.Order" scope ="prototype" >
<property name="emailer" ref ="smtpEmailer" />
</ bean >
September 2006
Agenda
An introduction to AOP
New and cool in AspectJ
Spring AOP
Spring AspectJ integration
Demos
Q&A
September 2006
Spring AOP basics
� A proxy-based AOP framework
� JDK proxies
� CGLIB proxies
� Targets many J2EE use cases
� Powerful integration with AspectJ
� Allowing tapping into full AOP features
September 2006
Proxy
Spring AOP schematic
Target
Object
Advice
Advisor
Pointcut
September 2006
Configuring through XML:Defining advisor
<bean id ="spamPreventionAdvisor"
class ="o.s.aop.support.DefaultPointcutAdvisor" >
</ bean >
<property name="advice" >
<bean class ="example.SpamPreventionInterceptor" />
</ property >
<property name="pointcut" >
<bean class ="o.s.aop.support.JdkRegexpMethodPointcut" >
<property name="pattern" value =".*send.*" />
</ bean >
</ property >
September 2006
Configuring through XML:Creating proxy<bean id ="emailerTarget" class ="example.EmailerImpl" >
</ bean >
<bean id ="emailer" class ="o.s.aop.framework.ProxyFactoryBean" >
<property name="target" ref ="emailerTarget" />
<property name="interceptorNames" >
<list >
<value >spamPreventionAdvisor </ value >
</ list >
</ property >
<property name="proxyInterfaces" >
<list >
<value >example.Emailer </ value >
</ list >
</ property >
</ bean >
Target
Advice/Advisor
Proxy interface(optional)
September 2006
Bean client
package example;
...
public class Main {
public static void main(String[] args ) {
ApplicationContext context
= new ClassPathXmlApplicationContext( "beans.xml" );
Emailer emailer = (Emailer)context.getBean( "emailer" );
emailer.send( "[email protected]" ,
"Hi! Your paypal account..." );
emailer.send( "[email protected]" ,
"Hi, I have an AspectJ question..." );
}
}
September 2006
Agenda
An introduction to AOP
New and cool in AspectJ
Spring AOP
Spring AspectJ integration
Demos
Q&A
September 2006
Proxy
Where AspectJ helps Spring AOP
Target
Object
Typed AdviceAspectJ Expression Pointcut
@AspectJ Aspects
September 2006
Spring-AspectJ integration
� Provides power of AspectJ in Spring
� Levels of integration
� Proxy-based mechanism—no special compiler• AspectJ pointcut expression
−Easier and expressive way to select pointcuts
• Typed advice−XML-based aspects definition with plain Java classes
•@AspectJ aspects−Express aspects with little XML
� Special compiler or weaver• Full power AspectJ
September 2006
AspectJ pointcut expression
� AspectJExpressionPointcut
� Still uses proxy-based mechanism
• Limitation of method-only interception
<bean id ="spamPreventor"
class ="o.s.aop.support.DefaultPointcutAdvisor" >
<property name="advice" >
<bean class ="example.SpamPreventionInterceptor" />
</ property >
<property name="pointcut" >
<bean class ="o.s.aop.aspectj.AspectJExpressionPointcut" >
<property name="expression"
value ="execution(* send(..))" />
</ bean >
</ property >
</ bean >
September 2006
Typed advice
� Problem: MethodInterceptor and its cousins take parameters of type Object.
� Solution: Use AspectJ style type-safe interception
September 2006
Typed advice: Defining aspect
<beans ...><aop:config >
<aop:aspect id ="emailLoggerBean"ref ="emailerLogger" >
<aop:beforepointcut ="execution(* send(String, String))
and args(address, *)" method ="log" />
</ aop:aspect ></ aop:config >
<bean id ="emailerLogger" class ="example.EmailLogger" />
...</beans>
September 2006
Plain Java aspect
package example;
public class EmailLogger {
public void log(JoinPoint.StaticPart tjpsp,
String address) {
System.err.println(
"Invoking " + tjpsp.getSignature() +
" for " + address);
}
}void before(Method method, Object[] args,
Object target) throws Throwable;
September 2006
Do away with XML: @AspectJ
package example;
@Aspectpublic class EmailLogger {
@Before( execution(* send(String, String))
&& args(address, *)" )
public void log(JoinPoint.StaticPart tjpsp, String address) {
System.err.println("Invoking " + tjpsp.getSignature() + " for " + address);
}}
September 2006
Using @AspectJ aspect
<beans ...>
<aop:autoproxy/ >
<bean id ="emailerLogger"
class ="example.EmailLogger" />
... Other beans ...
</beans>
September 2006
Choosing Spring AOP vs. AspectJ
� Use Spring AOP when
� Method-only interception is sufficient
• Full power of AOP overwhelming
� Don’t want to use special compiler
� Domain object’s don’t need to be crosscutted
� Pre-written aspects meet your needs
� Use AspectJ when
� Otherwise…
September 2006
Summary
� Spring AOP is simple, yet powerful way to modularize crosscutting concerns
� AspectJ integration bring full power of AOP in the Spring environment
� Incremental path from Spring AOP to AspectJ is available
The fun has just began…
September 2006
Resources
� Spring books
� Pro Spring, by Rob Harrop and Jan Machacek
� Professional Java Development with the Spring Framework, by Rod Johnson, Rod Johnson, Juergen Hoeller, Alef Arendsen, Thomas Risberg, ColinSampaleanu
� Spring in Action, by Craig Walls
� AspectJ books
� AspectJ in Action, by Ramnivas Laddad
� Eclipse AspectJ, by Adrian Colyer, Andy Clement, George Harley, Matthew Webster
� DI using aspect� Adrian Coyler, Dependency injection with AspectJ and Spring
http://www.ibm.com/developerworks/java/library/j-aopwork13.html
September 2006
AOP training from the source
Core AOP:
Simplifying Enterprise Applications
with AOP
November 7-10, Washington, DC
http://interface21.com/training
Spring Conference: The Spring Experience 2006December 7th – 10th, Hollywood Florida
by Interface21 and NoFluffJustStuff Java Symposiums
� World-class technical conference for the Spring community� 3 full days, 5 concurrent tracks, 60 sessions
• Core Spring 2.0• Core Enterprise 2.0• Core Web 2.0• Domain Driven Design• Just Plain Cool
� Enjoy five-star beach resort and amenities� Converse with core Spring team and industry experts
� Rod Johnson, Adrian Colyer, Ramnivas Laddad, Juergen Hoeller, etc.� Registration at http://www.thespringexperience.com
September 2006
Questions?
Ramnivas Laddad
Email: [email protected]
Web: http://interface21.com
Blog: http://ramnivas.com/blog