How much do you know about the core idea of spring?

Dependency injection

Dependency injection is a manifestation of surface interface programming and is the core idea of ​​Spring. In fact, dependency injection is not a sophisticated technique, just being packaged in such a way by Sping seems a bit mysterious.

class Main {
    interface Language {
        void print(String s);
    }

    static class Java implements Language{
        @Override
        public void print(String x) {
            System.out.println("System.out.print(\""+ x +"\")");
        }
    }

    static class Coder {
        private Language lang = new Java();

        public void helloWorld() {
            lang.print("hello world");
        }
    }

    public static void main(String[] args) {
        Coder coder = new Coder();
        coder.helloWorld();
    }
}

As shown in the code listing above, Coder uses the Java language to print the helloworld string, where it not only relies on the Language interface but also on the Java class, which makes it coupled with the Java class. It is easy to eliminate this dependence or decoupling

    interface Language {
        void print(String s);
    }

    static class Java implements Language{
        @Override
        public void print(String x) {
            System.out.println("System.out.print(\""+ x +"\")");
        }
    }

    static class Coder {
        private Language lang;

        public void setLang(Language lang) {
            this.lang = lang;
        }

        public void helloWorld() {
            lang.print("hello world");
        }
    }

    public static void main(String[] args) {
        Coder coder = new Coder();
        Language java = new Java();
        coder.setLang(java);
        coder.helloWorld();
    }
}

We added a method for setting a specific language to the Coder class, so that the Coder class only depends on the Language interface and not on the specific language implementation. In other words, the Coder class is decoupled from the specific language. At this time, we can easily use other languages ​​instead of Java. , For example using C#

static class CSharp implements Language{
    @Override
    public void print(String x) {
        System.out.println("Console.Write(\""+ x +"\")");
    }
}


public static void main(String[] args) {
    Coder coder = new Coder();
    Language csharp = new CSharp();
    coder.setLang(csharp);
    coder.helloWorld();
}

This technique of externally setting the specific object that an object depends on is dependency injection, which is very exciting. One of the most common coding techniques still has such a name.

For the Coder class, determining which language to use is originally determined during the compiler period. After dependency injection is used, which language is used will be delayed to runtime.

The core idea of ​​the Spring framework is based on this, but its implementation goes further. It makes the process of creating each object setting dependency dynamic and generalized. In our code listing, the main method of creating objects and setting dependencies is only applicable to the current situation, and Spring's IOC container can be applied to any situation

Generally, Spring's dependency relationship is represented by XML, and the IOC container parses XML to complete object creation and dependency injection.

We will implement the previous code with the Spring framework

interface Language {
    void print(String s);
}
class Java implements Language{
    @Override
    public void print(String x) {
        System.out.println("System.out.print(\""+ x +"\")");
    }
}
class CSharp implements Language{
    @Override
    public void print(String x) {
        System.out.println("Console.Write(\""+ x +"\")");
    }
}
class Coder {
    private Language lang;

    public void setLang(Language lang) {
        this.lang = lang;
    }

    public Language getLang() {
        return lang;
    }

    public void helloWorld() {
        lang.print("hello world");
    }
}

Dependency will be realized by XML configuration

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="java" class="Java">
    </bean>

    <bean id="csharp" class="CSharp">
    </bean>

    <bean id="coder" class="Coder">
        <property name="lang" ref="csharp"></property>
    </bean>
</beans>

The code to create the Coder object becomes

public static void main(String[] args) {
    ApplicationContext context = new FileSystemXmlApplicationContext("applicationContext.xml");
    Coder coder = (Coder) context.getBean("coder");
    coder.helloWorld();
}

The specific object creation and dependency setting will be completed by the IOC according to the XML configuration.

Spring automates the dependency injection mechanism, but the nature of dependency injection has not changed.

Aspect-oriented programming

Aspect-oriented programming can realize dynamic enhancements without changing the original code, such as doing certain things before or after a method is executed, such as recording logs, calculating running time, and so on.

Aspectj is perfectly integrated in Spring, so aspect-oriented programming is very convenient.

Spring Aspectj has several annotations to implement commonly used aspect-oriented programming functions

@Aspect
public class Logger {
    @Before("execution(* controller.Default.*(..))")
    public void before(JoinPoint join){}

    @After("execution(* controller.Default.*(..))")
    public void after(){}

    @AfterReturning("execution(* controller.Default.*(..))")
    public void afterReturning() {}

    @AfterThrowing("execution(* controller.Default.*(..))")
    public void afterThrowing(){}

    @Around("execution(* controller.Default.*(..))")
    public void around(ProceedingJoinPoint jp) {}
}

As shown in the code above, this class enhances all methods under the controller.Default class.

@Before annotation

The method modified by the @Before annotation will be executed before the enhanced method is executed

@After annotation

The method modified by the @After annotation will be executed after the enhanced method is executed

@AfterReturning annotation

The method modified by the @AfterReturning annotation will be executed after the enhanced method is executed, but the premise is that the modified method is successfully executed. If the method throws an exception halfway, the method modified by the AfterReturning annotation will not be executed, and the After annotation The modified method is executed anyway.

@AfterThrowing annotation

The method modified by the @AfterThrowing annotation will be executed when the enhanced method execution error throws an exception.

@Around annotation

@Around annotation is a synthesis of @Before annotation and @After annotation, it can be enhanced before and after the enhanced method

@Around("execution(* controller.Default.*(..))")
public void around(ProceedingJoinPoint jp) {
    try {
        System.out.println("before");
        jp.proceed();
        System.out.println("after");
    } catch (Throwable e) {
        System.out.println(e.getMessage());
    }
}

Using this annotation, the enhanced method needs to be manually coded and called

jp.proceed();

If this sentence is not written in the enhanced code, then the enhanced method will not run.

In addition, there is an important annotation @Pointcut

@Pointcut annotation

This annotation can be used to refine the entry point

@Aspect
public class Logger {
    @Pointcut( value = "execution(* controller.Default.*(..))")
    public void pointcut() {}
    
    @Before("pointcut()")
    public void before(JoinPoint join){}

    @After("pointcut()")
    public void after(){}

    @AfterReturning("pointcut()")
    public void afterReturning() {}

    @AfterThrowing("pointcut()")
    public void afterThrowing(){}

    @Around("pointcut()")
    public void around(ProceedingJoinPoint jp) {}
}

@Before, @After and other annotations can apply the entry point declared by this annotation, thereby reducing code duplication.

Guess you like

Origin blog.csdn.net/Lubanjava/article/details/100084602