Linuxea
Linuxea

Reputation: 329

How to invoke methods each other by spring?

How can I do to invoke methods in one service each other by spring?

I have one Service, I make it manage by spring by annotation @Service, but I found In this service, methods invoke each other is not manage by spring, So some annotation in spring I use makes no sense.

@Service
class Service {

    method a(){
        b(); // it's not invoked by spring, actually, it's invoked in a common way
    }

    method b(){
    }
}

It's work by using SpringContextHolder.getBean(Service.class).b();.But I wanna to know there is a more convenient way ?

Thank you very much.


update

I found something confused. It's ok to inject itself eventually. And I found something wrong when I use my custom annotation @LogTime over a method, which results in the inject component is null !!!!!

for example:

 //  @LogTime
  public Response execute(Request request) {
    try {
      return okHttp.client.newCall(request).execute();
    } catch (IOException e) {
      log.error("OkHttp wrong", e);
      throw new SystemException("OkHttp wrong", e);
    }
  }

When I use @LogTime annotation I created over this method, the client component is null!!!!!!


update finally

@Component
public class OkHttp {

  private final OkHttpClient client;
  private final OkHttp okHttp;

  public OkHttp(OkHttpClient client, @Lazy OkHttp okHttp) {
    this.client = client;
    this.okHttp = okHttp;
  }
}

summarize:

It's ok to inject self, but it's not ok to use okHttp.client.method(). the okHttp.client is null and client is not null, It's ok to replace okHttp.client.method with client.method() directly. the client is managed by spring, so we can achieve the same goal.

Upvotes: 3

Views: 2169

Answers (2)

Alex Salauyou
Alex Salauyou

Reputation: 14348

The common way is to use dependency injection, e.g. with @Autowired:

@Service
class MyService {

  @Autowired
  MyService thisService;  // inject a service itself

  public void a() {
    thisService.b();    // now, `b` will be called in a transaction
  }

  @Transactional
  public void b() {
    // ...
  } 

}

Though, this is a poor design: such bean cannot live outside a container.

Upvotes: 1

Shailendra
Shailendra

Reputation: 9102

I found In this service, methods invoke each other is not manage by spring

You need to understand that Spring manages objects and calls made to methods of those objects via proxies ( read official documentation here for more details. In this documentation you will get to know the reason why method to method calls within same class is not "managed" ). These proxies can differ in that they can be Dynamic, CGlib or any other depending on how they are created. You can mentally imagine a proxy in between whenever there is spring managed class method calling another spring managed different class method. However in case of a method calling another method of same class it's pure method call without proxy because there is no opportunity to intercept the call and add behavior.

Upvotes: 2

Related Questions