concept

Reflection is a feature of the Java language that allows programs to examine themselves and operate on internal members at runtime (not compile time). To put it simply, a program dynamically retrieves properties and methods of a class at run time and calls objects called reflection. Conversely, it fixes which objects and methods are called in the code.

The advantages and disadvantages

Advantages: Can achieve dynamic object creation and compilation, reflecting a great deal of flexibility. Let the user get the object of the newly added class without changing the code. Cons: Performance affects.

How does Spring’s IOC use reflection

We all know that Spring is an IOC container implemented through reflection and factory patterns, so why use reflection? Let’s look at factory mode without reflection:

// Define the interface
interface fruit{
    public abstract void eat();
} 

// Interface implementation classes Apple and Orange
class Apple implements fruit{
     public void eat(){
         System.out.println("Apple"); }}class Orange implements fruit{
     public void eat(){
         System.out.println("Orange"); }}/ / the factory class
class Factory{
     public static fruit getInstance(String fruitName){
         fruit f=null;
         if("Apple".equals(fruitName)){
             f=new Apple();
         }
         if("Orange".equals(fruitName)){
             f=new Orange();
         }
         returnf; }}/ / run
public class hello{
     public static void main(String[] a){
         fruit f=Factory.getInstance("Orange"); f.eat(); }}Copy the code

Obviously, the downside of this is that when we add a subclass, we need to modify the factory class. If we add too many subclasses, we will change too much. The factory pattern is implemented with reflection:

// Define the interface
interface fruit{
     public abstract void eat();
}

// Interface implementation classes Apple and Orange
class Apple implements fruit{
    public void eat(){
         System.out.println("Apple"); }}class Orange implements fruit{
    public void eat(){
        System.out.println("Orange"); }}/ / the factory class
class Factory{
    public static fruit getInstance(String ClassName){
        fruit f=null;
        try{
            f=(fruit)Class.forName(ClassName).newInstance();
        }catch (Exception e) {
            e.printStackTrace();
        }
        returnf; }}/ / run
class hello{
    public static void main(String[] a){
        // I need to get an Apple instance object
        fruit f=Factory.getInstance("Reflect.Apple");
        if(f! =null){ f.eat(); }}}Copy the code

With reflection, the factory class does not need to be modified, even if we need to add as many subclasses as possible. The factory pattern implemented using reflection can get an instance of the interface through reflection, but requires passing in the full package and class name. The user also has no way of knowing how many subclasses an interface can use, so we configure the required subclasses in the form of properties files.

Rough analysis of IOC

The most basic technique in IOC is “Reflection” programming, which is to dynamically generate objects based on a given class name (in the form of a string). This kind of programming allows objects to be determined as they are generated. However, objects to be produced in Spring are defined in configuration files to improve flexibility and maintainability.

The working mode of the IOC container can be thought of as a refinement of the factory mode. The IOC container can be thought of as a factory in which objects to be produced are defined in the configuration file and then generated based on the class names given in the configuration file using the reflection mechanism provided by the programming language. From an implementation point of view, IOC takes the object generation code that was previously written down in the factory approach and changes it to a configuration file definition. In other words, the factory and object generation are separated separately in order to improve flexibility and maintainability.