5

To my impression, RmiProxyFactoryBean is supposed to produce a proxy object instance that is of type AccountService that will be injected to accountService property of SimpleObject instance in the following code.

What I do not understand is why does the XML file seem to instruct Spring to inject an object of RmiProxyFactoryBean type to accountService property of SimpleObject object instance? I'm expecting an explicit instruction from the XML file that tells the Spring how to get an AccountService instance from RmiProxyFactoryBean instance instead of injecting an RmiProxyFactoryBean instance. I find this confusing.

public class SimpleObject {

    private AccountService accountService;

    public void setAccountService(AccountService accountService) {
        this.accountService = accountService;
    }
}


<bean class="example.SimpleObject">
    <property name="accountService" ref="accountService"/>
</bean>

<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
    <property name="serviceUrl" value="rmi://HOST:1199/AccountService"/>
    <property name="serviceInterface" value="example.AccountService"/>
</bean>

Source: http://static.springsource.org/spring/docs/2.5.x/reference/remoting.html (see 17.2.2.)

Thanks

supertonsky
  • 2,563
  • 6
  • 38
  • 68

2 Answers2

5

Because Proxy Beans wrap the object in question, they pretend to be the interface that is being called (and then later actually call that interface).

The RmiProxyFactoryBean returns a proxy object so that when your code thinks it is calling a method on your example.AccountService class, it's actually being called on a bean with the same interface as your example.AccountService interface as specified here:

<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
    ...
    <property name="serviceInterface" value="example.AccountService"/>
</bean>

Say there was a method on the interface called example.AccountService.reconcile(Long amount) (just for sake of example)...

If you called this normally the method calling it would just push it into the stack. But if the example.AccountService object is returned from the RmiProxyFactoryBean as it is above, it will be wrapped in a proxy bean. This proxy bean has a method inside of it that is also named reconcile and also has an argument of Long amount, which makes it indistinguishable from the original example.AccountService bean which it wraps. This way the proxy bean can have code that it runs, before, after, or instead of the code that is in the actual example.AccountService.reconcile(Long amount) method.

Proxy beans come from a whole different way of programming called Aspect Oriented Programming (AOP) which deals with cross-cutting-concerns; i.e. code that doesn't clearly seem to fit within the confines of normal OOP separation of concerns. Some of these concerns are For instance, transaction demarcation, security, and logging.

It appears that you are doing this rather manually above, but it's sometimes easier to weave these in at runtime using SpringAOP which has a language for selecting and applying proxy beans to existing code.

However, take note to program to interfaces rather than to program to just classes.

leeand00
  • 25,510
  • 39
  • 140
  • 297
  • Please correct me if I'm wrong...I've written this a bit hastily. – leeand00 Sep 30 '11 at 02:36
  • Thanks leeand00, but I'm not sure if I clearly get your point. What I asked is how does Spring know where to get the proxy object? I know that the proxy factory produces proxy object that implements the interface you specified, but how does the Spring know where to get this instance from the factory? Usually if you declare a bean and you want to tell Spring how to instantiate an object, you have to specify it e.g. . But in the given code, there isn't anything like that. – supertonsky Sep 30 '11 at 02:54
  • Is it like Spring scans all the methods from your factory and see if it could return a type that matches the property of your bean and inject it if it does? – supertonsky Sep 30 '11 at 03:33
  • @supertonsky I see your point, you specify an interface, and not an implementation. It may have to do with the naming of the beans / naming of the class...(*sigh*, if I remember correctly...) there's a thing in Spring called Autowiring which might be behind this...can anyone confirm this? – leeand00 Sep 30 '11 at 03:50
  • @supertonsky I see your point, you specify an interface, and not an implementation. It may have to do with the naming of the beans / naming of the class...(*sigh*, if I remember correctly...) there's a thing in Spring called Autowiring which might be behind this...can anyone confirm this? Spring does an awful lot behind the scenes, lots of meta programming...actually see this question: http://stackoverflow.com/questions/6594908/spring-autowire-fundamentals (See the first scenario) – leeand00 Sep 30 '11 at 03:55
  • Yes, Spring supports autowiring by name, type, etc. But in the given code, the "RmiProxyFactoryBean" itself is being injected as "AccountService" type to "SimpleObject"'s accountService property, which of course is not of the same type as the target of injection. I don't understand how could Spring possibly know that it's a factory and that it need not assign the factory itself but get a proxy instance from the factory and inject it. It really looks counter intuitive to me. It looks like it's trying to assign the factory itself and not the instance coming from the factory. – supertonsky Sep 30 '11 at 06:13
2

A more succinct way of putting it is that the RmiProxyFactoryBean implements the FactoryBean interface. Implementing that interface instructs the Spring bean factory that this class is a factory itself, causing Spring to invoke the getObject() method on that class and return the result as the bean, rather than creating an instance of the class itself and returning.

So, short answer, it's a built-in mechanic of Spring.

pap
  • 27,064
  • 6
  • 41
  • 46