mercredi 22 avril 2020

Does java spring caching break reflection?

I'm using spring boot and integrated caching recently. Within my tests I use reflection a bit.

Here is an example:

@Service
public class MyService {

    private boolean fieldOfMyService = false;

    public void printFieldOfMyService() {
        System.out.println("fieldOfMyService:" + fieldOfMyService);
    }

    @Cacheable("noOpMethod")
    public void noOpMethod() {
    }

}

And this is the test:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { MyApplication.class })
public class MyServiceTest {

    @Autowired
    private MyService myService;

    @Test
    public void test() throws Exception {

        myService.printFieldOfMyService();

        boolean fieldOfMyService = (boolean) FieldUtils.readField(myService, "fieldOfMyService", true);

        System.out.println("fieldOfMyService via reflection before change:" + fieldOfMyService);

        FieldUtils.writeField(myService, "fieldOfMyService", true, true);

        boolean fieldOfMyServiceAfter = (boolean) FieldUtils.readField(myService, "fieldOfMyService", true);

        System.out.println("fieldOfMyService via reflection after change:" + fieldOfMyServiceAfter);

        myService.printFieldOfMyService();

    }

}

As you can see it's quite simple:

  • MyService has a private field fieldOfMyService
  • the test changes this from false to true via reflection

problem

  • everything works fine without caching.. this is the output:
fieldOfMyService:false
fieldOfMyService via reflection before change:false
fieldOfMyService via reflection after change:true
fieldOfMyService:true

Now I activate caching via:

  • @EnableCaching in spring
  • and then you get this:
fieldOfMyService:false
fieldOfMyService via reflection before change:false
fieldOfMyService via reflection after change:true
fieldOfMyService:false                      <<<<< !!!

Long story short:

  • when caching gets activated the service seems to be immune against changes made via reflection

The funny thing is, this only happens when the according service actually uses caching via at least one @Caching annotated method. In case the service does not have this like:

@Service
public class MyService {

    private boolean fieldOfMyService = false;

    public void printFieldOfMyService() {
        System.out.println("fieldOfMyService:" + fieldOfMyService);
    }

}

.. then it still works.

I guess this has something to do with the layers which get added when caching is activated. But... why? And is there a solution to it?

Thanks in advance for your help :-)





Aucun commentaire:

Enregistrer un commentaire