Introduction and verification of Dagger2 dependency injection singleton

Business component instantiation actually has a large number of application scenarios in enterprise applications. In enterprise applications, the overhead on the JVM under the scenario of frequent creation and destruction of object instances can be unimaginable. Instantiation can reduce the burden of JVM memory management and improve application performance, especially in e-commerce and big data application scenarios In the process of explosive requests pouring into the server, if the components are not singled, it may directly lead to system crash. In particular, some applications sharing JVM will even burst the JVM setting memory, resulting in memory overflow, dragging down other system applications, and even the whole platform avalanche. This is also the reason why the singleton mode is widely used in enterprise applications, and it is also the important value of singleton.

For Android devices with so few poor performance resources and a considerable amount of system available overhead, the demand for component singleton is naturally hungry. Compared with traditional devices, Android system can't afford developers to waste and waste resources. In the whole process of taking over Ioc, whether Dagger2 can undertake the application's demand for component instantiation is more prominent in the coding demand.

Define a business class:

package com.tc.app.dagger2.di.singleton;

import android.util.Log;

/**
 *
 * @author min.weixm
 * @version $$Id: Abusiness, v 0.1 2021/11/16 23:17 min.weixm Exp $$
 */
public class Abusiness {

   public Abusiness(){}

   public void display(){
      Log.i("[Abusiness.display()]","Abusiness.display() called");
   }
}

Define a Module for the business:

package com.tc.app.dagger2.di.singleton;

import dagger.Module;
import dagger.Provides;

/**
 *
 * @author min.weixm
 * @version $$Id: ABusinessModule, v 0.1 2021/11/20 20:33 min.weixm Exp $$
 */
@Module
public class ABusinessModule {


   @Provides
   public Abusiness provideMyBusinessA() {
      return new Abusiness();
   }
}

Define a Component without loss of integrity:

package com.tc.app.dagger2.di;

import com.tc.app.dagger2.MainActivity;
import com.tc.app.dagger2.di.singleton.ABusinessModule;

import javax.inject.Singleton;

import dagger.Component;

/**
 * The real instance is not provided. The real instance is provided by MyBusinessApartModule
 *
 * @author min.weixm
 * @version $Id: MyApartComponent.java, v 0.1 2021/11/12 14:40 min.weixm Exp $
 */
@Component(modules = {ABusinessModule.class})
public interface MyApartComponent {

   void inject(MainActivity activity);
}

Next, we actually inject our business class. The key codes are as follows:

/** Business service instances injected through dependencies */
@Inject
Abusiness abusinessX;

@Inject
Abusiness abusinessY;

By injecting business object instances respectively, we can easily observe whether the Hash values of the two objects are consistent. The complete code is as follows:

package com.tc.app.dagger2;

import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.tc.app.dagger2.di.DaggerMyApartComponent;
import com.tc.app.dagger2.di.singleton.Abusiness;

import javax.inject.Inject;

public class MainActivity extends AppCompatActivity {

   /** Business service instances injected through dependencies */
   @Inject
   Abusiness abusinessX;

   @Inject
   Abusiness abusinessY;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      this.setContentView(R.layout.activity_main);
      Toolbar toolbar = findViewById(R.id.toolbar);
      setSupportActionBar(toolbar);

      FloatingActionButton fab = findViewById(R.id.fab);
      fab.setOnClickListener((view) ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                  .setAction("Action", null).show()
      );

      //Initialize the environment and complete the function call
      DaggerMyApartComponent.create().inject(this);
      Log.i("---------------abusinessX---------------", "" + abusinessX);
      Log.i("---------------abusinessY---------------", "" + abusinessY);
   }

   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.menu_main, menu);
      return true;
   }

   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
      int id = item.getItemId();
      if (id == R.id.action_settings) {
         return true;
      }
      return super.onOptionsItemSelected(item);
   }
}

After executing build, the running result log is as follows:

I/---------------abusinessX---------------: com.tc.app.dagger2.di.singleton.Abusiness@91dbc1d
I/---------------abusinessY---------------: com.tc.app.dagger2.di.singleton.Abusiness@c681e92

Through the running results, it can be seen that although Dagger2 automatically injects corresponding business instances, the Hash values of the two objects are not consistent. In fact, two completely different instances are initialized. In order to ensure that the injected object is Singleton, we begin to add corresponding @ Singleton tags to Module and Component.

The Module code is as follows:

package com.tc.app.dagger2.di.singleton;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;

/**
 *
 * @author min.weixm
 * @version $$Id: ABusinessModule, v 0.1 2021/11/20 20:33 min.weixm Exp $$
 */
@Module
public class ABusinessModule {


   @Provides
   @Singleton
   public Abusiness provideMyBusinessA() {
      return new Abusiness();
   }
}

The Component code is as follows:

package com.tc.app.dagger2.di;

import com.tc.app.dagger2.MainActivity;
import com.tc.app.dagger2.di.singleton.ABusinessModule;

import javax.inject.Singleton;

import dagger.Component;

/**
 * The real instance is not provided. The real instance is provided by MyBusinessApartModule
 *
 * @author min.weixm
 * @version $Id: MyApartComponent.java, v 0.1 2021/11/12 14:40 min.weixm Exp $
 */
@Component(modules = {ABusinessModule.class})
@Singleton
public interface MyApartComponent {

   void inject(MainActivity activity);
}

Keep the injection method unchanged. We run it again after build ing the code. The results are as follows:

I/---------------abusinessX---------------: com.tc.app.dagger2.di.singleton.Abusiness@91dbc1d
I/---------------abusinessY---------------: com.tc.app.dagger2.di.singleton.Abusiness@91dbc1d

A magical scene appears. Although the corresponding business instances in our Module are new, after adding the @ Singleton tag, the instances injected by Dagger2 can ensure that the business instances are the same no matter where and how many times they are introduced.

Keywords: Java Android Design Pattern

Added by devain on Sat, 20 Nov 2021 16:29:50 +0200