Showing posts with label AOP. Show all posts
Showing posts with label AOP. Show all posts

Friday, February 4, 2011

Spring AOP - Changing target of a Proxy at runtime

I had a pretty strange usecase where i wanted to change the target object of the proxy and runtime. Spring makes it so simple to use.

My usecase was as follows



ApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:META-INF/spring/aop-poc-module-context.xml");
AccountDAO accountDao = (AccountDAO) ctx.getBean("accountDao");

IAccount account = accountDao.getById(123);

System.out.println("account" + account);

account.setName("sudheer");

System.out.println("account" + account);



Is a property is change on the entity , i want to change the entity object itself , that is , in the above use two sysouts will print different objects.

The use case arose because i was using a cache(infinispan) which did not allow modifying POJOs outside a transaction scope.

I did achieve the same using the follwing



public class AccountDAO {

private Advisor advisor;

//This is get methods of the accountDao

public IAccount getById(long id) {
//creating new account - to mock database behavior
IAccount a = new Account(369, "suji");
//Using spring factory
ProxyFactory pf = new ProxyFactory();
pf.setExposeProxy(true);
pf.addInterface(IAccount.class);
//Using by own Target source to change the Target
pf.setTargetSource(new SwappableTargetSource(a));
//advisor which holds the advice and pointcut
pf.addAdvisor(advisor);
return (IAccount) pf.getProxy();
}

public void setAdvisor(Advisor advisor) {
this.advisor = advisor;
}

}



My advice class



public class SwappableBeforeAdvice implements MethodBeforeAdvice {

@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("Before advice called");

if (!((IAccount) target).isWritable()) {

//Changing the target source based on specific business condition
((SwappableTargetSource) ((Advised) AopContext.currentProxy())
.getTargetSource()).swap(new Account(56, "dan"));
}

}
}



My custom target source



public class SwappableTargetSource implements TargetSource {

private Object target;

public SwappableTargetSource(Object initialTarget) {
this.target = initialTarget;
}

public synchronized Class<?> getTargetClass() {
return this.target.getClass();
}

public final boolean isStatic() {
return false;
}

public synchronized Object getTarget() {
return this.target;
}

public void releaseTarget(Object target) {
// nothing to do
}

public synchronized void swap(Object newTarget)
throws IllegalArgumentException {
this.target = newTarget;
}

@Override
public boolean equals(Object other) {
return (this == other || (other instanceof SwappableTargetSource && this.target
.equals(((SwappableTargetSource) other).target)));
}

@Override
public int hashCode() {
return SwappableTargetSource.class.hashCode();
}

@Override
public String toString() {
return "SwappableTargetSource for target: " + this.target;
}

}



These are the spring xml configuration.



<bean id="accountDao" class="com.test.dao.account.AccountDAO">
<property name="advisor" ref="settersAdvisor" />
</bean>

<bean id="swapableBeforeAdvice" class="com.test.framework.SwappableBeforeAdvice"/>



This is the advice which advise all setter methods on the bean



<bean id="settersAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="swapableBeforeAdvice" />
</property>
<property name="patterns">
<list>
<value>.*set.*</value>
</list>
</property>
</bean>



Thanks to this post in spring forum which helped me do this.

http://forum.springsource.org/showthread.php?t=102784

Saturday, November 21, 2009

AOP - AspectJ,Spring - Compile Time ,Load Time ,Run Time(Proxy)

Spring AOP - Runtime - Using Proxy

Steps

1.Spring Application Context - Bean Declarations

For enabling this proxy approach add
<aop:aspectj-autoproxy />

Note :

Do not be misled by the name of the element: using it will result in the creation of Spring AOP proxies. The @AspectJ style of aspect declaration is just being used here, but the AspectJ runtime is not involved



Aspect Declaration
<bean id="myAspect" class="com.test.aop.MyAspect"></bean>

Method where aspect will be applied
<bean id="test" class="com.test.aop.Test" init-method="init" />

Wrapper calling test
<bean id="testB" class="com.test.aop.Wrapper" init-method="init">
<property name="test" ref="test"></property>
</bean>


2. Classes

  • Aspect Class

@Aspect
public class MyAspect {

@Before("execution(* com.test.aop.Test.*())")
public void myMethod()
{
System.out.println("calling my before aspect");
}

}

  • public class Test {

public void init()
{
System.out.println("init in test method");
}

}


  • public class Wrapper {

private Test test;

public void setTest(Test test) {
this.test = test;
}

public void init() {
test.init();
}

}

3. OutPut(In Spring DM)

System.out I init in test method
System.out I calling my before aspect
System.out I init in test method

Only when the init method is called through testB bean ,the aspect is bound.

Now when init method of test bean is called , the aspect is still not bound.(init methods cannot be proxied).

This is because the way spring life cycle works :

Spring life cycle

Phase 1 - Validate bean definitions
Phase 2 - Bean definition post processor(replacing property values)
Phase 3 - Bean Instantiation
Phase 4 - Bean post initialization(setters and init methods -in order) & Proxy creation

In the above example bean 'test' first cycles through phase 1,2,3 and 4. Hence after the init method is called, the proxy is created.But when testB is created in its init(phase) call to bean test will call teh aspect (as bean test lifecycle is complete)

One more important thing to note is that Cg lib will be used to create proxy here as teh class doesnt implement any interface.(Else jdk dyanmic proxies would have been used)

Aspect-J Load Time Weaving
(This may have issues with Spring DM
http://forum.springsource.org/showthread.php?t=80504
)

Same code as above except some change in the configurations.

1. Replace <aop:aspectj-autoproxy /> with <context:load-time-weaver/>.

2. Add aop.xml in META-INF directory

<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>

<!--works without this -->
<weaver>
<include within="com.test.aop.*" />
</weaver>

<aspects>
<!-- weave in just this aspect -->
<aspect name="com.test.aop.MyAspect" />
</aspects>

</aspectj>


3. Class to test the application in standlone mode

public class StandAloneLoadTimeWeaving {

public static void main(String args[])
{
ApplicationContext ctx = new ClassPathXmlApplicationContext("config.xml",StandAloneLoadTimeWeaving.class);
Test t =(Test)ctx.getBean("test");
t.init();
}

}

Ref: http://www.springbyexample.org/examples/aspectj-ltw.html
http://static.springsource.org/spring/docs/2.5.x/reference/aop.html#aop-aj-ltw


4. Add the following parameter when running

-javaagent:spring-agent.jar


Aspect J Compile Time Weaving(Build Time)

Same as Loadtime weaving needs aop.xml (but no need to add spring agent while running)

Command to compile the code

java org.aspectj.tools.ajc.Main –inpath <src_code_directory> -outjar <output_jarname.jar>

Ex:java -cp aspectjtools.jar;aspectjrt.jar org.aspectj.tools.ajc.Main -inpath . -outjar test.jar

The output jar will have code which is instrumented by the aspect.

You can download aspectj from this site

http://www.eclipse.org/aspectj/downloads.php

Saturday, November 7, 2009

Spring Training -Day 2

Bean name will be generated by bean id. Context.getBean(name) hence works by id.

Writing custom annotation – write custom annotation and register pre-processor to add custom logic to it.

BeanPostProcessor- deals with objects – postInit & preInit

Interceptor- aspect with single advice[will be called when bean is created]

isSingleton method inside factory will be called only once if isSingletonMethod() set to true –Doesn’t make sense if factory itself is prototype

Inheritance – bean can be marked as

abstract=true - instance wont be created

Parent – parent=”” – for overriding

PropertyEditors- how properties are converted in xmls which always are mentioned as string ex – toDate,Integer etc –Spring has many of its own

We can register our own propertyeditors - For any type –call our propertyEditor – this is not like set of interceptors instead editor is picked from a map.

Following conventions - put customEditor in same package as code , and name should be <type>+Editor - no need to explicitly register the editor.

Import configuration file - <import resource=”ddsdsd.xml” />

P namespace – allows properties to be set as attributes in bean definition.

Util namespace – loading properties – diff from propertyplaceholder – util :properties , set,list,Map,reading constants

AOP
------

2 technologies

Spring Aop – Runtime –Using Dynamic Proxy

AspectJ- Compile Time OR Load Time –byte code injection

Performance – aspectj build time is best but complex.

For AspectJ : http://www.infoq.com/articles/Orchestration-Oleg-Zhurakousky;jsessionid=E64F684641DCF76CEC10633EFF108059

Spring Aop – uses (hides this complexity)

a. uses JDK dynamic proxy when interface is mentioned

Ref: http://java.sun.com/j2se/1.4.2/docs/guide/reflection/proxy.html

Method invocations on an instance of a dynamic proxy class are dispatched to a single method in the instance's invocation handler, and they are encoded with a java.lang.reflect.Method object identifying the method that was invoked and an array of type Object containing the arguments.

b. uses CGlib when no interface is mentioned

CGLIb can be forced in both cases using Proxy-target-class=false in definition.

Creating proxy using APIs - org.springframework.aop.framework.ProxyFactory;

Can add advice to the proxy – which recognizes either annotations or anything else

Adding aspectj weaving adds a context weaving classloader

Hierarchy --- BootClassLoader,Aop Context weaving Classloader,Extension loader,Application loader

The above happens for only Aspectj Based viewing

Hence all classes other than in boot path can be intercepted.

Delegation Of Classloader – first goes to parent if class def is not found and then comes down

When using jdk dynamic proxy –cast to interfaces

CGlib works by extending the class definition and then creating instance of that , old object is GC’ed.

Hence with final classes it throws error

Constructor gets called twice.- because extended.

Internal methods don’t get called.

JdkDynamic uses the same instance

JointPoint- execution context

PointCut - Expression

Advice-method

Aspect- class

Advice -@Before,@Afterreturning,@AfterThrowing,@After,@Around

Spring JDBC
---------------

No checked exception – all run time exceptions –rarely Db exceptions are recoverable

Callback pattern – give ur reference to some to call u at right times

Does from Getting connections, Participating in Transaction, Execution of statement, Processing ResultSet, Handling Exceptions, Closing connection.

Need to provide a datasource along with transactionManager. – Datasource manages the connection pooling

We can use Apache DBCP or C3po for pooling.

JdBCTemplate methos like queryForMap,queryForList

RowMapper – Each Row maps to a Doman Object
RowCallBackHandler – No return value
ResultSetExtractor - Multiple rows map to a single object.

Spring handles all exceptions irrespective of the vendor. It keeps a internal mapping of all error codes specific to the vendor, and gives very descriptive errors.

Thursday, November 13, 2008

Spring AOP Basics

The best atricle i have come across to start with Spring AOP
http://www.javabeat.net/articles/51-introduction-to-springs-aspect-oriented-programminga-1.html
This can be followed by Spring tutorial from www.springframework.org

 
Free Domain Names @ .co.nr!