This is a caption for the header image with link

Java Developer's favorite

Spring Framework

Spring makes programming Java quicker, easier, and safer for everybody.

This post is a start guide of Spring framework.

Overview

The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications - on any kind of deployment platform.

A key element of Spring is infrastructural support at the application level: Spring focuses on the “plumbing” of enterprise applications so that teams can focus on application-level business logic, without unnecessary ties to specific deployment environments.

Spring makes it easy to create Java enterprise applications. It provides everything you need to embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM, and with the flexibility to create many kinds of architectures depending on an application’s needs. As of Spring Framework 5.1, Spring requires JDK 8+ (Java SE 8+) and provides out-of-the-box support for JDK 11 LTS. Java SE 8 update 60 is suggested as the minimum patch release for Java 8, but it is generally recommended to use a recent patch release.

Spring supports a wide range of application scenarios. In a large enterprise, applications often exist for a long time and have to run on a JDK and application server whose upgrade cycle is beyond developer control. Others may run as a single jar with the server embedded, possibly in a cloud environment. Yet others may be standalone applications (such as batch or integration workloads) that do not need a server.

Spring is open source. It has a large and active community that provides continuous feedback based on a diverse range of real-world use cases. This has helped Spring to successfully evolve over a very long time.

IOC Container and Beans

Foremost amongst these is the Spring Framework’s Inversion of Control (IoC) container. A thorough treatment of the Spring Framework’s IoC container is closely followed by comprehensive coverage of Spring’s Aspect-Oriented Programming (AOP) technologies. The Spring Framework has its own AOP framework, which is conceptually easy to understand and which successfully addresses the 80% sweet spot of AOP requirements in Java enterprise programming.

Introduction

IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.

The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory.

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.

Container

The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It lets you express the objects that compose your application and the rich interdependencies between those objects.

Several implementations of the ·ApplicationContext interface· are supplied with Spring. In stand-alone applications, it is common to create an instance of ClassPathXmlApplicationContext or FileSystemXmlApplicationContext. While XML has been the traditional format for defining configuration metadata, you can instruct the container to use Java annotations or code as the metadata format by providing a small amount of XML configuration to declaratively enable support for these additional metadata formats.

The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the ApplicationContext is created and initialized, you have a fully configured and executable system or application.

Spring

The Spring IoC container

Configuring Metadata

As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application.

Configuration metadata is traditionally supplied in a simple and intuitive XML format.

These bean definitions correspond to the actual objects that make up your application. Typically, you define service layer objects, data access objects (DAOs), presentation objects such as Struts Action instances, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth. Typically, one does not configure fine-grained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create and load domain objects. However, you can use Spring’s integration with AspectJ to configure objects that have been created outside the control of an IoC container. See Using AspectJ to dependency-inject domain objects with Spring.

The following example shows the basic structure of XML-based configuration metadata

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">  
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>
  • The id attribute is a string that identifies the individual bean definition.
  • The class attribute defines the type of the bean and uses the fully qualified classname.

Instantiating a Container

The location path or paths supplied to an ApplicationContext constructor are resource strings that let the container load configuration metadata from a variety of external resources, such as the local file system, the Java CLASSPATH, and so on.

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

The following example shows the service layer objects (services.xml) configuration file:



<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- services -->

    <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="itemDao" ref="itemDao"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for services go here -->

</beans>

The following example shows the data access objects daos.xml file:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for data access objects go here -->

</beans>

In the preceding example, the service layer consists of the PetStoreServiceImpl class and two data access objects of the types JpaAccountDao and JpaItemDao (based on the JPA Object-Relational Mapping standard). The property name element refers to the name of the JavaBean property, and the ref element refers to the name of another bean definition. This linkage between id and ref elements expresses the dependency between collaborating objects.

Composing XML-based Configuration Metadata

It can be useful to have bean definitions span multiple XML files. Often, each individual XML configuration file represents a logical layer or module in your architecture.

You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple Resource locations. Alternatively, use one or more occurrences of the <import/> element to load bean definitions from another file or files. The following example shows how to do so:

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

In the preceding example, external bean definitions are loaded from three files: services.xml, messageSource.xml, and themeSource.xml. All location paths are relative to the definition file doing the importing, so services.xml must be in the same directory or classpath location as the file doing the importing, while messageSource.xml and themeSource.xml must be in a resources location below the location of the importing file. As you can see, a leading slash is ignored. However, given that these paths are relative, it is better form not to use the slash at all. The contents of the files being imported, including the top level <beans/>element, must be valid XML bean definitions, according to the Spring Schema.

Using the Container

The ApplicationContext is the interface for an advanced factory capable of maintaining a registry of different beans and their dependencies. By using the method T getBean(String name, Class<T> requiredType), you can retrieve instances of your beans.

The ApplicationContext lets you read bean definitions and access them, as the following example shows:

// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// use configured instance
List<String> userList = service.getUsernameList();

With Groovy configuration, bootstrapping looks very similar. It has a different context implementation class which is Groovy-aware (but also understands XML bean definitions). The following example shows Groovy configuration:

ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");

The most flexible variant is GenericApplicationContext in combination with reader delegates — for example, with XmlBeanDefinitionReader for XML files, as the following example shows:

GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();

You can also use the GroovyBeanDefinitionReader for Groovy files, as the following example shows:

GenericApplicationContext context = new GenericApplicationContext();
new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy");
context.refresh();

You can then use getBean to retrieve instances of your beans. The ApplicationContext interface has a few other methods for retrieving beans, but, ideally, your application code should never use them. Indeed, your application code should have no calls to the getBean() method at all and thus have no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides dependency injection for various web framework components such as controllers and JSF-managed beans, letting you declare a dependency on a specific bean through metadata (such as an autowiring annotation).

For example, to generate a simple object “Hello”, we can use beans to help create it.

public class Hello {
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}

In the Resource, there is a new xml file called bean.xml and before the creation of the Spring framework, it should load the .jar files from maven first.

Import"jar"FIle

Import ".jar" Files

XML

XML file Detail
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--Using Spring to create objects, Bean is the generator in Spring
    Type  Name  = new Type();
    Hello hello = new Hello();
    id          = name
    class       = new Object;
    property is to assign a value to the object
    -->

    <bean id="Hello" class="Hello">
        <!-- additional collaborators and configuration for this bean go here -->
            <property name="str" value="Spring"/>
    </bean>
    <!-- more bean definitions for data access objects go here -->

</beans>

And finally, the testing method looks like what the code below describes:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class myTest {
    public static void main(String[] args){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        Hello hello = (Hello) context.getBean("Hello");
        System.out.println(hello.toString());
    }
}

Spring Configuration

  1. ailas By using ailas, the constructor can be called by another name. Adding a extra line in the xml and we can use the ailas.

     <alias name="Hello" alias="hhhh"/>
    
     ublic class myTest {
     public static void main(String[] args){
         ApplicationContext context = new ClassPathXmlApplicationContext( "bean.xml");
         Hello hello = (Hello) context.getBean("hhhh");
         System.out.println(hello.toString());
         }
     }
    

    And the output is also

     Hello{str='Spring'}
        
    

    Also, using name in the properties can be called.

     <bean id="Hello" class="Hello" name="sk">
    

    Then test it using “sk”

     ublic class myTest {
     public static void main(String[] args){
         ApplicationContext context = new ClassPathXmlApplicationContext( "bean.xml");
         Hello hello = (Hello) context.getBean("sk");
         System.out.println(hello.toString());
         }
     }
    

    The outout is also:

     Hello{str='Spring'}
        
    
  2. Import

    Assume that there is a team colarborating with each other to exploit, import can combine the beans to be a whole entity. Usually, different beans are in charge of different part of calsses, and the configurations are rendered in different beans. We can combine these beans to be a whole configuration file.

    In the applicationContext.xml, there imports other three beans:

         <?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.xsd">
         <import resource="bean.xml"/>
         <import resource="bean1.xml"/>
         <import resource="bean2.xml"/>
     </beans>
    

Dependency Input

Through Set:

  • Dependencies: The creation of Bean objects is depended on the container
  • Input: The properties of Bean objects are depended on the container

For example:

There are classes named students and Adrress having complcated types,

import javafx.beans.property.Property;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class student {

    private String name;
    private Address address;
    private  String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Property info;

    @Override
    public String toString() {
        return "student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    public void setInfo(Object info) {
        this.info.setValue(info);
    }

    public String getName() {
        return name;
    }

    public Address getAddress() {
        return address;
    }

    public String[] getBooks() {
        return books;
    }

    public List<String> getHobbys() {
        return hobbys;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public Set<String> getGames() {
        return games;
    }

    public String getWife() {
        return wife;
    }

    public Object getInfo() {
        return info.getName();
    }

    public Property infoProperty() {
        return info;
    }
}

Class Addess:

public class Address {
    private String address;

    public void setAddress(String address) {
        this.address = address;
    }

    public String getAddress() {
        return address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}

The properties of complicated types can be demonstrated as follows:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address" class="Address" name="sk">
           <property name="address" value="SH"/>
    </bean>
    <bean id="student" class="student" name="student2">
        <property name="name" value="danny"/>
        <property name="address" ref="address"/>
        <!--Array-->
        <property name="books">
            <array>
                <value>Harri Porter</value>
                <value>Red Mansion</value>
                <value>Gone With the Wind</value>
            </array>
        </property>
        <!--List-->
        <property name="hobbys">
            <list>
                <value>Music</value>
                <value>Reading</value>
            </list>
        </property>
        <!--Map-->
        <property name="card">
            <map>
                <entry key="ID" value="111111111"/>
                <entry key="BankCard" value="00000000"/>
            </map>
        </property>
        <!--Set-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>CF</value>
            </set>
        </property>
        <!--NULL-->
        <property name="wife">
            <null></null>
        </property>
        <!--Properties-->
        <property name="info">
            <props>
                <prop key="IDcard">10010</prop>
                <prop key="sex">Male</prop>
            </props>
        </property>
    </bean>

    <!-- more bean definitions for data access objects go here -->

</beans>

Scope of dependencies

When you create a bean definition, you create a recipe for creating actual instances of the class defined by that bean definition. The idea that a bean definition is a recipe is important, because it means that, as with a class, you can create many object instances from a single recipe.

You can control not only the various dependencies and configuration values that are to be plugged into an object that is created from a particular bean definition but also control the scope of the objects created from a particular bean definition. This approach is powerful and flexible, because you can choose the scope of the objects you create through configuration instead of having to bake in the scope of an object at the Java class level. Beans can be defined to be deployed in one of a number of scopes. The Spring Framework supports six scopes, four of which are available only if you use a web-aware ApplicationContext. You can also create a custom scope.

BEANSCOPE

Bean Scope
  • Singleton(default)

    SINGLETON

      <bean id="accountService" class="com.something.DefaultAccountService"/>
      <!-- the following is equivalent, though redundant (singleton scope is the default) -->
      <bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
    
  • Prototype

      <bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
    

    prototype

Auto-configuration

```xml
<bean id="cat" class="cat">
    <property name="name" value="ROll"/>
</bean>
<bean id="dag" class="dog">
    <property name="name" value="WangCai"/>
<!--
    byName: will find the context in the container where the `bean id` is the same as the the object's `set()` method  
    byType: will find the context in the container where the class is the same as the the object class.  
-->
<bean id="people" class="people" autowire="byName">
    <property name="name" value="Danny"/>
</bean>
```
  • ByName autowire

It needs to ensure that the id of all the beans are sole, and this bean needs to be kept consistent with the value of the setter’s property taht is automatically inputted.

  • ByType autowire

It needs to ensure that the class of all the beans are sole, and this bean needs to be kept consistent with the class’s property taht is automatically inputted.

Annotation-based Container Configuration

The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML. The short answer is “it depends.” The long answer is that each approach has its pros and cons, and, usually, it is up to the developer to decide which strategy suits them better. Due to the way they are defined, annotations provide a lot of context in their declaration, leading to shorter and more concise configuration. However, XML excels at wiring up components without touching their source code or recompiling them. Some developers prefer having the wiring close to the source while others argue that annotated classes are no longer POJOs and, furthermore, that the configuration becomes decentralized and harder to control.

No matter the choice, Spring can accommodate both styles and even mix them together. It is worth pointing out that through its JavaConfig option, Spring lets annotations be used in a non-invasive way, without touching the target components source code and that, in terms of tooling, all configuration styles are supported by the Spring Tools for Eclipse.

  1. Import constraint: context constraint
  2. Configurate the annotation suport: context:annotation-config/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>

@Autowired Annotation & @Qualifier

For example, in the previous instance, we can add @Autowired annotation before the objects creation. Besides, if one @Autowired cannot finish assemble the objects, we can add @Qualifier(Value="XXX") to configurate the use of @Autowired, and determine one only bean object:

 import org.springframework.beans.factory.annotation.Autowired;

 public class people {
    @Autowired
    @Qualifier(Value="cat111")
    private cat Cat;
    @Autowired
    @Qualifier(Value="dog222")
    private dog Dog;
    private String name;
 

In the beans.xml, the code can be simplified:

    <bean id="cat" class="cat"/>
    <bean id="cat111" class="cat"/>
    <bean id="dag" class="dog"/>
    <bean id="dag222" class="dog"/>

    <bean id="people" class="people" autowire="byName">
        <property name="name" value="Danny"/>
    </bean>

@Resource Annotation

 public class people {
    @Resource
    private cat Cat;
    @Resource
    private dog Dog;
    private String name;
  • The differences between @Resource and @Autowired
    • They can both be applied in the process of automatical configuration, and can both be put at the property configurations.
    • @Autowired is realized through byName, and the corresponding object must exist.
    • @Resource is realized through byName by default, if it cannot find the key words, it will realize through byType. If both of the two method cannot find, it will generate an error.
    • The execution order of there two methods are various: @Autowired by byType while @Resource by byName in default.
    • @Nullable can make the instance to be NULL.

@Component Annotation

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <!--
        To scan the particular package, 
        and the annotations below these packages will work
        -->
    <context:component-scan base-package="com.danny"/>
    <context:annotation-config/>

</beans>

The @Component makes the auto-generation. And @Value("XXX") assign the value to the object.

package com.danny.proj;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//Equals to <bean id="user" class="com.Danny.poroj.User">
@Component
public class User {
    public String name;
    //Equals <property name="name" value="Danny"/>
    @Value("Danny")
    public void setName(String name) {
        this.name = name;
    }
}
  • Derived annotations:
    • dao: @Repository
    • service: @Service
    • controller: @Controller

Java Configuration

Project class:

@Component
public class User {
    private String name;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    //Equals <property name="name" value="Danny"/>
    @Value("Danny")
    public void setName(String name) {
        this.name = name;
    }
}

Configuration class:

@Configuration //This annotation means the class will be collocated by the spring container.
// And be injected into the container. Because itself is a @Component, the same as beans,xml
public class hhhConfig {
    @Bean //Sign up for a bean, it is the same as a bean tag
          //The name of this method is the same as "id" in the bean
          //The return value of this method is the "class" property the bean tag.
    public static User user(){
        return new User();
    }
}

Testing class:

import com.danny.config.hhhConfig;
import com.danny.proj.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class myTest {
    public static void main(String[] args){
        ApplicationContext context = new AnnotationConfigApplicationContext(hhhConfig.class);
        User user = (User) context.getBean("user()");
//        System.out.println(getUser.getname());
        System.out.println(user.getName());
    }
}

AOP - Aspect Oriented Programming with Spring

(additional reference: https://www.tutorialspoint.com/springaop/springaop_overview.htm) !(https://www.tutorialspoint.com/springaop/springaop_overview.htm)

Aspect-oriented Programming (AOP) complements Object-oriented Programming (OOP) by providing another way of thinking about program structure. The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects enable the modularization of concerns (such as transaction management) that cut across multiple types and objects. (Such concerns are often termed “crosscutting” concerns in AOP literature.)

One of the key components of Spring is the AOP framework. While the Spring IoC container does not depend on AOP (meaning you do not need to use AOP if you don’t want to), AOP complements Spring IoC to provide a very capable middleware solution.

The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Dependency Injection helps you decouple your application objects from each other, while AOP helps you decouple cross-cutting concerns from the objects that they affect. AOP is like triggers in programming languages such as Perl, .NET, Java, and others.

Spring AOP module lets interceptors intercept an application. For example, when a method is executed, you can add extra functionality before or after the method execution.

Core Concepts in AOP

Before we start working with AOP, let us become familiar with the AOP concepts and terminologies. These terms are not specific to Spring, rather they are related to AOP.

AspectA module which has a set of APIs providing cross-cutting requirements. For example, a logging module would be called AOP aspect for logging. An application can have any number of aspects depending on the requirement.
Join pointThis represents a point in your application where you can plug-in AOP aspect. You can also say, it is the actual place in the application where an action will be taken using Spring AOP framework.
AdviceThis is the actual action to be taken either before or after the method execution. This is the **actual piece of code that is invoked during program execution by Spring AOP framework.
PointCutThis is a set of one or more joinpoints where an advice should be executed. You can specify PointCuts using expressions or patterns as we will see in our AOP examples.
IntroductionAn introduction allows you to add new methods or attributes to existing classes.
Target objectThe object being advised by one or more aspects. This object will always be a proxied object. Also referred to as the advised object.
AOP proxyAn object created by the AOP framework in order to implement the aspect contracts (advise method executions and so on). In the Spring Framework, an AOP proxy is a JDK dynamic proxy or a CGLIB proxy.
WeavingWeaving is the process of linking aspects with other application types or objects to create an advised object. This can be done at compile time, load time, or at runtime.

Using Spring to Configurate Aop

To configure a log to a particular methods, it can apply AOP in spring to gnerate a pointcut.

In the Maven dependencies, except the basic org.springframework depndency, there needs a special dependency called org.aspectj.

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

In the parent interface, there are three methods to be implimented:

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

To implement theses methods,

public class UserServiceTmp1 implements UserService {


    public void add() {
        System.out.println("Add one client");
    }

    public void delete() {
        System.out.println("Delete one client");
    }

    public void update() {
        System.out.println("Update one client");
    }

    public void select() {
        System.out.println("Select one client");
    }
}

Then, there will create a AfterLog class to inspect the execution of the code:

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class log  implements MethodBeforeAdvice {
    //method: the executable target's method
    //args: Arguments
    //target: The target object
    public void before(Method method, Object[] args, Object target) throws Throwable{
        System.out.println(target.getClass().getName()+" " + method.getName()+ " has been executed.");
    }
}

There is also a BeforeLog class:

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class log  implements MethodBeforeAdvice {
    //method: the executable target's method
    //args: Arguments
    //target: The target object
    public void before(Method method, Object[] args, Object target) throws Throwable{
        System.out.println(target.getClass().getName()+" " + method.getName()+ " has been executed.");
    }
}

In the applicationContext.xml, there should configureate the Spring Aop:

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

    <bean id="userService" class="com.Danny.service.UserServiceTmp1"/>
    <bean id="log" class="com.Danny.log.log"/>
    <bean id="afterLog" class="com.Danny.log.AfterLog"/>

    <!--Method 1: Use original Spring API Interface-->
    <!--Configurate aop-->
    <aop:config>
        <!--pointCut and its location-->
        <aop:pointcut id="pointcut" expression="execution(* com.Danny.service.UserServiceTmp1.*(..))"/>

        <!--Advisor increase-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

Finally, the output of the log is the following:

com.Danny.service.UserServiceTmp1 add has been executed.
Add one client
addMethodhas been executed and the returning value is null

Self-defined Aop

We can also define the point cut and the aspect by ourself.

Firstly, create a diy class which defines self-defined pointcuts to execute.

public class DiyPointCut {
    public void before(){
        System.out.println("====Before execution====");
    }
    public void after(){
        System.out.println("====After execution====");
    }
}

Then, in the applicationContext.xml, we can configurate the pointcut,

<!--Self-defined Pointcut, ref: the referred class-->
    <aop:config>
        <aop:aspect ref="diy">
            <!--Point Cut-->
            <aop:pointcut id="point" expression="execution(* com.Danny.service.UserServiceTmp1.*(..))"/>
            <!--Aspect-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

The out put looks like the following:

====Before execution====
Add one client
====After execution====

Annotation Aop Configuation

In the applicationContext.xml, add a configuration code:

 <!--Annotation Aop-->
    <bean id="annotationPointCut" class="com.Danny.diy.annotationPointCut"/>
    <aop:aspectj-autoproxy/>

In the pointcut class, we can use @Aspect annotation to implicate the pointcut class, and we can annotate the @Before or @After method to execute. The @Around can both execute the after method and the before method.

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Around;

@Aspect //To annotate this is a pointcut
public class annotationPointCut {

    @Before("execution(* com.Danny.service.UserServiceTmp1.*(..))")
    public void before(){
        System.out.println("====Before execution====");
    }

    @After("execution(* com.Danny.service.UserServiceTmp1.*(..))")
    public  void after(){
        System.out.println("====After execution====");
    }
}

    @Around("execution(* com.Danny.service.UserServiceTmp1.*(..))")
    //In the Around type, we can give a parameter to determine the point cut
    public void around(ProceedingJoinPoint jp) throws Throwable{
        System.out.println("Before around");
        Object proceed = jp.proceed(); //Execute the method
        System.out.println("After around");
        Signature signature = jp.getSignature();//get Signature
        System.out.println("signature: " + signature);
        System.out.println(proceed);
    }

Output is the following:

Before around
====Before execution====
Add one client
====After execution====
After around
signature: void com.Danny.service.UserService.add()
null