Spring proxy jdk vs cglib

Simple version:

Aspectj static weaving: do the aop at compile time using Aspectj’s own compiler: ajc.

JDK Proxy: when class implements some interface. The proxy will implement every interface. It can NOT be cast to the original target class because it’s simply a dynamic proxy that happens to implement the same interface(s) as the target

CGLIB: When class is concrete without any interface. The proxy will subclass the target.

Note: the JDK-proxy and CGLIB is transparent to the user.

Less simple version

超详细中文版

1. What proxies Spring uses?

There are two types of proxies available:

JDK proxy, which is comes out of the box in JDK and CGLib, which is created by the CGLib library (3rd party dependency).

JDK Proxy only works with beans that implement an interface (which in my view is a good thing, you should code to intreface not concrete classes) and it is also the Spring recommended way of using AOP.

Quote from Spring doc:

As it is good practice to program to interfaces rather than classes, business classes normally will implement one or more business interfaces.

However, there are lots of people out there who like to code concrete classes and therefore must use CGLib. This means that there should be a cglib.jar on classpath to make it work and there is also a side effect whereby your proxy constructors will run twice – so use constructors only for dependency injection (no business logic allowed)

2. How does spring AOP knows what proxy to use?

Configuration mostly come from <aop:config/>, <tx:annotation-driven/>, <aop:aspectj-autoproxy/> and <aop:scoped-proxy/> as well as some configurable properties on some factory beans.

The important thing to remember is that some of these configs are merged before being processed.

Quote from Spring doc:

Multiple <aop:config/> sections are collapsed into a single unified auto-proxy creator at runtime, which applies the strongest proxy settings that any of the <aop:config/> sections (typically from different XML bean definition files) specified. This also applies to the <tx:annotation-driven/> and <aop:aspectj-autoproxy/> elements.
To be clear: using ‘ proxy-target-class=”true”‘ on <tx:annotation-driven/>, <aop:aspectj-autoproxy/> or <aop:config/> elements will force the use of CGLIB proxies for all three of them.

So be careful when defining these tags in multiple xml configuration files.

Now in order to enforce JDK proxy the following configuration must be used: <aop:config proxy-target-class=”false”>

Example:

    &lt;aop:config proxy-target-class="false"&gt;
        &lt;aop:advisor advice-ref="runtimeCacheAdvice" pointcut="execution(* com..ErpRuntimeContextInternal.providePreferences(..))"&gt;
...
    &lt;/aop:advisor&gt;&lt;/aop:config&gt;

Make sure that all of config tags have the proxy-target-class set to false. However this does not affect the TransactionProxyFactoryBean (if you are using ORM)

In order to use JDK proxies for your transactional beans you must set proxyTargetClass property to false.

Example:

&lt;bean id="txSecurityProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
    &lt;description&gt;
        NOTE: see org.springframework.transaction.TransactionDefinition
        disable transactions by default (bean must explicitly specify)
    &lt;/description&gt;
    &lt;property name="transactionManager" ref="transactionManager"&gt;
    &lt;property name="proxyTargetClass" value="false"&gt;
    &lt;property name="transactionAttributes"&gt;
        &lt;props&gt;
            &lt;prop key="*"&gt;PROPAGATION_NOT_SUPPORTED&lt;/prop&gt;
        &lt;/props&gt;
    &lt;/property&gt;
&lt;/property&gt;&lt;/property&gt;&lt;/bean&gt;

For CGlib the corresponding proxyTargetClass and proxy-target-class should be set to true.

As you may have noticed I use XML configuration for Spring and some people may find it ancient approach suitable only for those who like the Flinstones. However, my view is that annotations polute your code because they are directly applied to your classes. Image if you use Spring annotations, The some JPA, then some JAXB then some other 3rd party libraries annotation – it is a complete mess! With XML you create POJO’s and then define separate XML configurations for your application concerns like: ORM, DTO, Spring, cache and so on. Moreover each of these confiurations can be changes without touching the code. So I think it is much better from the SOLID point of view. (and yes I did enjoy the Flinstones, so there). But if you are a big fan of annotations I am sure you can google for the corresponding configs.

3. Now that you now everything – or do you?

Now you may think that you know everything and you got your app working like you want – think again! In what order do your aspects execute?

Yes, if you have transactions and then ehcache and then some performance logging you may have several proxies! So you need to order them so that you know precisely when and if your aspects get executed. Use the order attribute.

Example:

 
    &lt;aop:config proxy-target-class="false"&gt;
        &lt;aop:advisor advice-ref="runtimeCacheAdvice" order="100" pointcut="execution(* com..ErpRuntimeContextInternal.providePreferences(..))"&gt;
...
    &lt;/aop:advisor&gt;&lt;/aop:config&gt;
So now hopefully you get the bigger picture of how AOP works in Spring and major gotchas that you may encounter.

FROM HERE

Another link about getting object behind the proxy.

Joinpoint VS ProceedingJoinPoint in AOP using aspectJ

If you use before,after-throwing,after-returning and after use Jointpoint.

@Pointcut("execution(* com.pointel.aop.test1.AopTest.beforeAspect(..))")  
public void adviceChild(){}  

@Before("adviceChild()")  
public void beforeAdvicing(JoinPoint joinPoint /*,ProceedingJoinPoint pjp - used refer book marks of AOP*/){ 

    //Used to get the parameters of the method !
    Object[] arguments = joinPoint.getArgs();
    for (Object object : arguments) {
        System.out.println("List of parameters : " + object);
    }

    System.out.println("Method name : " + joinPoint.getSignature().getName());
    log.info("beforeAdvicing...........****************...........");
    log.info("Method name : " + joinPoint.getSignature().getName());
    System.out.println("************************"); 
}

If you use around use Proceedingjoinpoint .

An around advice is a special advice that can control when and if a method (or other join point) is executed. This is true for around advices only, so they require an argument of type ProceedingJoinPoint, whereas other advices just use a plain JoinPoint. A sample use case is to cache return values:

private SomeCache cache;

@Around("some.signature.pattern.*(*)")
public Object cacheMethodReturn(ProceedingJoinPoint pjp){
    Object cached = cache.get(pjp.getArgs());
    if(cached != null) return cached; // method is never executed at all
    else{
        Object result = pjp.proceed();
        cache.put(pjp.getArgs(), result);
        return result;
    }
}

In this code (using a non-existent cache technology to illustrate a point) the actual method is only called if the cache doesn’t return a result. This is the exact way the Spring EHCache Annotations project works, for example.

Another specialty of around advices is that they must have a return value, whereas other advice types must not have one.

use xml config

Note the pjp.proceed() will call the real method it arounds. 

	<aop:config>
		<!-- ***** Pointcut Definitions ***** -->
		<aop:pointcut id="allServicePointcut"
			expression="bean(*Service) or bean(*ServiceExternal) and not within(org.xxx.xxx.server.ws..*)" />

		<!-- ***** Aspects ***** -->
		<!--
			Aspect to handle transaction management for all internal and external
			service API's.
		-->
		<aop:aspect id="hibernateProxyRemovalAspect" ref="hibernateProxyRemovalAdvice" order="3">
			<aop:around pointcut-ref="allServicePointcut" method="removeProxy" />
		</aop:aspect>
	</aop:config>

	<bean id="hibernateProxyRemovalAdvice"
		class="org.xxx.framework.dao.HibernateProxyRemovalAdvice">
		<property name="hibernateProxyRemover" ref="hibernateProxyRemover" />
	</bean>

	<bean id="hibernateProxyRemover"
		class="org.xxx.framework.dao.HibernateProxyRemover" />
// Imports
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * Advice that removes hibernate proxy objects.
 */
public class HibernateProxyRemovalAdvice
{
    private HibernateProxyRemover hibernateProxyRemover;

    public Object removeProxy(ProceedingJoinPoint pjp) throws Throwable
    {
        return hibernateProxyRemover.removeProxy(pjp.proceed());
    }

    public HibernateProxyRemover getHibernateProxyRemover()
    {
        return hibernateProxyRemover;
    }

    public void setHibernateProxyRemover(HibernateProxyRemover hibernateProxyRemover)
    {
        this.hibernateProxyRemover = hibernateProxyRemover;
    }
}

Secrets of the Spring AOP Proxy

Spring Aspect Oriented Programming (AOP) is a powerful mechanism to weave cross cutting concerns like security, transactions, exception handling, logging, etc. into business code (“core concerns”) without explicitly adding calls to the cross cutting concern.  This allows the cross cutting concern to be updated, removed, swapped out, and generally maintained in a much simpler fashion.

AOP UNDER THE COVERS – THE PROXY

Having said that, because of the way AOP is implemented, there can seem to be a certain amount of mystery and magic at work.  Your code never invokes the advice methods of an aspect class.  Spring does it for you based on your XML configuration or annotations on the aspect class.  How does the magic happen?  Under the covers, Spring implements a proxy to intercept calls to a target object.

As an example, say you have a service bean that invokes a call to the saveCustomer( ) method on a DAO.

image

Now say you want to have some logging (a cross cutting concern) occur when a call to any save method occurs on a DAO.  Spring detects your need to call on a logging aspect through your AOP configuration or annotations.  When it does, it builds a proxy (called CustomerDaoProxy for example sake here) around the “target” object – in this case the DAO.

image

Now, on a call to a save method in the DAO, the proxy intercepts the call and routes it appropriately to the appropriate advice method in the aspect class.

image

ISSUES GIVEN PROXY-BASED AOP

This proxy-based mechanism allows powerful cross cutting concern code to be isolated from business code.  However, there are all kinds of “gotcha’s” that can occur with this type of under-the-covers implementation of which you should be aware.  First of all, aspects cannot advise other aspects.  Per the Spring documentation:

Advising aspects with other aspects?

In Spring AOP, it is not possible to have aspects themselves be the target of advice from other aspects. The @Aspect annotation on a class marks it as an aspect, and hence excludes it from auto-proxying.  (See:  static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-at-aspectj).

This can have some big implications in, sometimes even limitations on, how you implement a cross cutting concern.  Say, for example, your form of logging required adding log statements to a database.  Further, say this database entry required to be performed as part of a transaction (probably a reasonable assumption).  If transactions were implemented through aspects, then you would have the log aspect a target of advice from a transaction aspect.  That’s a big “NGH” – not gonna happen.

image

Another such “gotcha” is that local or internal calls to methods within a target object do not cause the advice method to be invoked even with both methods are captured by the AOP pointcut.  In other words, a call from a method in a target to another method in the target does not get intercepted by the proxy.  This results in the advice method never being triggered.  For example, assume you had some sort of business bean that made a call to itself as shown in the simple example below.

   1: @Component("mySubordinate")
   2: public class CoreBusinessSubordinate {
   3:
   4:     public void doSomethingBig() {
   5:         System.out.println("I did something small");
   6:     }
   7:
   8:     public void doSomethingSmall(int x){
   9:         System.out.println("I also do something small but with an int");
  10:     }
  11: }

Also assume you had an aspect constructed and configured with a pointcut capturing both CoreBusinessSubordinate methods as the CrossCuttingConcern class shown here.

   1: @Component
   2: @Aspect
   3: public class CrossCuttingConcern {
   4:
   5:     @Before("execution(* com.intertech.CoreBusinessSubordinate.*(..))")
   6:     public void doCrossCutStuff(){
   7:         System.out.println("Doing the cross cutting concern now");
   8:     }
   9: }

If another bean was to explicitly call both the target doSomethingBig( ) and doSomethingSmall( ) methods directly, the proxy/interceptor of the aspect would cause the advice to fire twice – as expected.

   1: @Service
   2: public class CoreBusinessKickOff {
   3:
   4:     @Autowired
   5:     CoreBusinessSubordinate subordinate;
   6:
   7:     // getter/setters
   8:
   9:     public void kickOff() {
  10:         System.out.println("I do something big");
  11:         subordinate.doSomethingBig();
  12:         subordinate.doSomethingSmall(4);
  13:     }
  14: }

Results of calling kickOff above given code above.

I do something big

Doing the cross cutting concern now

I did something small

Doing the cross cutting concern now

I also do something small but with an int

However, if instead of calling the doSomethingSmall( ) method from another bean, it was called from inside the target as shown in this next example, the advice fires only one time!

   1: @Component("mySubordinate")
   2: public class CoreBusinessSubordinate {
   3:
   4:     public void doSomethingBig() {
   5:         System.out.println("I did something small");
   6:         doSomethingSmall(4);
   7:     }
   8:
   9:     public void doSomethingSmall(int x){
  10:         System.out.println("I also do something small but with an int");
  11:     }
  12: }
  13:
  14: --------------------------------------------
  15:
  16: public void kickOff() {
  17:     System.out.println("I do something big");
  18:     subordinate.doSomethingBig();
  19:     //subordinate.doSomethingSmall(4);
  20: }

New results of calling kickOff above.

I do something big

Doing the cross cutting concern now

I did something small

I also do something small but with an int

The internal call from the target method to another target method escapes the aspect interceptor.

WORK AROUND

You can sometimes find a work around for AOP proxy issues.  For example, you can work around this last issue by exposing the proxy to the target.  When configuring autoproxy development in your configuration, add an expose-proxy attribute and set its value to true (by default it is false).

   1: <aop:aspectj-autoproxy expose-proxy="true"/>

Now in your target code, you can reroute self-invocating methods back through the target proxy.  Use AopContext.currentProxy( ) to get the proxy object and then invoke the internal target method through the proxy as shown below.

   1: public void doSomethingBig() {
   2:     System.out.println("I did something small");
   3:     //doSomethingSmall(4);
   4:     ((CoreBusinessSubordinate) AopContext.currentProxy()).doSomethingSmall(4);
   5: }

Of course, take heed that this tightly couples your core business concern to AOP – something you are trying to avoid with AOP to begin with.  So it may be better to refactor the code such that internal calls are not required when you need advice to fire on all methods.
FROM HERE

modify method arguments using spring aspect

@Before

For logging kinds of stuff, we usually use the “@Before”

 

@Aspect
public class LoggingAspect {

    @Before("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
    public void logBefore(JoinPoint joinPoint) {

        System.out.println("logBefore() is running!");
        System.out.println("hijacked : " + joinPoint.getSignature().getName());
        System.out.println("******");
        
        //get args
        Object[] args = joinPoint.getArgs();
    }

}

A before advice gets a copy of the argument array, but it can’t modify the original arguments. 

 

 

@Around

So in order to modify , we need to use “@Around” with which you can pass the args to the execution!

 

@Around("execution(* de.foo.entity.*.set*(..)) && args(java.lang.String)")
public void checkAroundSetter(final ProceedingJoinPoint pjp)
    throws Throwable {
    LOGGER.debug(pjp.getSignature().toLongString());
    Object[] args = pjp.getArgs();
    for (int i = 0; i < args.length; i++) {
        if (args[i] instanceof String && ((String) args[i]).isEmpty()) {
            args[i] = null;
        }
    }
    pjp.proceed(args);
}

filter 和 aop

现在AOP的设计开发理念在软件开发中用的越来越广泛,在我们开发的软件中也广泛进行了使用。而最常用的就是filter和interceptor。
Filter

该过滤器的方法是创建一个类XXXFilter实现此接口,并在该类中的doFilter方法中声明过滤规则,然后在配置文件web.xml中声明他所过滤的路径
<filter>
<filter-name>XXXFilter</filter-name>
<filter-class>
com.web.util.XXXFilter
</filter-class>
</filter>

<filter-mapping>
<filter-name>XXXFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>

Interceptor

该过滤器的方法也是创建一个类XXXInterceptor实现此接口,在该类中intercept方法写过滤规则,不过它过滤路径的方法和Filter不同,它与strut.xml结合使用(其他开发框架各自有自己的切入点),

创建一个strus.xml的子配置文件struts-l99-default.xml,它继承与struts2的struts-default,此配置文件是其他子配置文件的父类,只要是继承与该文件的配置文件所声明的路径都会被它过滤 如下
<package name=”XXX-default” namespace=”/” extends=”struts-default”>

<interceptors>
<interceptor name=”authentication” />

<interceptor-stack name=”user”>
<interceptor-ref name=”defaultStack” />
<interceptor-ref name=”authentication” />
</interceptor-stack>

<interceptor-stack name=”user-submit”>
<interceptor-ref name=”user” />
<interceptor-ref name=”token” />
</interceptor-stack>

 

<interceptor-stack name=”guest”>
<interceptor-ref name=”defaultStack” />
</interceptor-stack>

 

<interceptor-stack name=”guest-submit”>
<interceptor-ref name=”defaultStack” />
<interceptor-ref name=”token” />
</interceptor-stack>

 

</interceptors>
<default-interceptor-ref name=”user” />

</package>
比较一,filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,而interceptor则基于java本身的反射机制,这是两者最本质的区别。
比较二,filter是依赖于servlet容器的,即只能在servlet容器中执行,很显然没有servlet容器就无法来回调doFilter方法。而interceptor与servlet容器无关。
比较三,Filter的过滤范围比Interceptor大,Filter除了过滤请求外通过通配符可以保护页面,图片,文件等等,而Interceptor只能过滤请求。
比较四,Filter的过滤例外一般是在加载的时候在init方法声明,而Interceptor可以通过在xml声明是guest请求还是user请求来辨别是否过滤。