You can often find yourself in a situation with many similar proxy definitions, especially when defining transactional proxies. By using parent and child bean definitions along with inner bean definitions, you can get much cleaner and more concise proxy definitions.

First, create a parent, template bean definition for the proxy, as shown below:

<bean id="txProxyTemplate" abstract="true"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
        <props>
            <prop key="*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

It is never instantiated on its own, so it may not be complete. Then, each proxy that needs to be created will be a child bean definition, wrapping the proxy target as an internal bean definition, since the target is never used on its own. The following example shows a child bean like this:

<bean id="myService" parent="txProxyTemplate">
    <property name="target">
        <bean class="org.springframework.samples.MyServiceImpl">
        </bean>
    </property>
</bean>

You can override the properties of the parent template. In the following example, we override the transaction propagation settings:

<bean id="mySpecialService" parent="txProxyTemplate">
    <property name="target">
        <bean class="org.springframework.samples.MySpecialServiceImpl">
        </bean>
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="store*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

Note that in the parent bean example, we explicitly marked the parent bean definition as abstract by setting the abstract attribute to true, so that its instance will actually was never actually created. Application contexts (but not simple bean factories) by default pre-create all singleton instances. So it's important (at least in the case of singleton beans) that if you have a (parent) bean definition that you're only going to use as a template, and that definition defines a class, then you need to make sure that the abstract attribute is set to true. Otherwise, the application context will actually try to pre-create an instance of it.

Creating an AOP proxy programmatically using ProxyFactory

Creating AOP proxies programmatically using Spring is very easy. This will allow you to use the Spring AOP module without depending on the Spring IoC module.

Interfaces implemented by the target are automatically proxied. The following listing demonstrates creating a proxy for a target with one interceptor and one advisor:

Java
ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
factory.addAdvice(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();
Kotlin
val factory = ProxyFactory(myBusinessInterfaceImpl)
factory.addAdvice(myMethodInterceptor)
factory.addAdvisor(myAdvisor)
val tb = factory.proxy as MyBusinessInterface

The first step is to create an object of type org.springframework.aop.framework.ProxyFactory. It can be created using a target object, as in the previous example, or you can specify the interfaces that will be proxied in an alternative constructor.

You can add tips (with interceptors as a specialized type of advice), advisors, or both, and manipulate them throughout the ProxyFactory lifecycle. If you add IntroductionInterceptionAroundAdvisor, the proxy can be forced to implement additional interfaces.

ProxyFactory also has convenience methods (inherited from AdvisedSupport) that allow you to add other types of advice, such as the "before" advice and the "throw exception" advice. AdvisedSupport is the superclass of ProxyFactory and ProxyFactoryBean.

Integrating AOP proxy creation with an IoC framework is a best practice in most applications. We recommend transferring the configuration from Java code to an external file using AOP, as should be done in general.