AOP in the Spring Core Family (part 1)

Today, I’m going to talk to you about AOP in Spring, aspect oriented programming, which plays an important role in the whole system of Spring. This article is still based on practice, annotation cut into injection, OK, article structure:

  1. @aspectj,
  2. Spring AOP-AspectJ annotations

1. The origin of @AspectJ

When it comes to AspectJ, many people have misconceptions. Many people only know that AspectJ uses the Aspect set of annotations in Spring, thinking that it is the set of annotations developed by Spring. I feel responsible for clarifying this with you. AspectJ is an AOP framework that enables AOP compilation of Java code (typically at compile time) and gives It AspectJ’s AOP capabilities (requiring a special compiler, of course). It can be said that AspectJ is the most mature and featured-rich language currently implementing AOP frameworks. More fortunately, AspectJ is fully compatible with Java programs and is almost seamless, making it easy for engineers with a Java programming background to get started and use. In fact, AspectJ is a separate language that requires a specialized compiler (ajC compiler). Spring AOP has the same purpose as ApectJ to handle crosscutting business uniformly, but unlike AspectJ, Spring AOP does not attempt to provide full AOP functionality (even if it is fully implementable). Spring AOP focuses more on integrating with the Spring IOC container and combining that advantage to solve crosscutting business problems, so AspectJ has a greater advantage in terms of AOP functionality. At the same time,Spring has noticed that AspectJ relies on a special compiler (ajC compiler) for the way AOP is implemented, so Spring wisely sidesteps this and turns to the implementation principles of dynamic proxy technology to build Spring AOP’s internal mechanisms (dynamic weaving). This is the most fundamental difference from AspectJ (static weaving). The development of the annotation style in the @aspect form was introduced after AspectJ 1.5, and Spring followed this approach very quickly, so Spring 2.0 uses the same annotations as AspectJ. Note that Spring only uses the same annotations as AspectJ 5, but it still doesn’t use AspectJ’s compiler. The underlying implementation is dynamic proxy technology, so it doesn’t rely on AspectJ’s compiler. So, it’s important to understand that while Spring AOP uses that set of annotations, the underlying implementation of AOP uses dynamic proxies (JDK or CGLib) to dynamically implant. Static migration of AspectJ is not the focus of this article, so I’ll just mention it.

2. Spring AOP-AspectJ annotations

When it comes to Spring AOP, veteran programmers should be aware that instead of using @aspect as a set of annotations and AOP: Config as an XML solution, developers defined their own classes to implement interfaces, and configuration was nasty. I won’t demonstrate it in this article, but then Spring made the decision to “integrate” AspectJ into Spring and turn on the AOP namespace. Now Sping AOP can be a big deal. Before the examples above, let’s mention all the concepts of AOP:

  • Pointcut: An expression that locates a specific method
  • Section: Cut point + voice advice
  • Voice behavior (enhancement): What to do after locating the method

There are a lot of concepts on the web, what join points, what weave, what target objects, what introduce. I personally feel that in the Spring AOP world of Java, it doesn’t matter at all. Don’t confuse yourself. Here’s an example: Maven dependency:

   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>4.2.3.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.2.3.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>4.2.3.RELEASE</version>
    </dependency>// The following two AspectJ dependencies are intended to introduce AspectJ annotations<dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.6.12</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.6.12</version>
    </dependency>//Spring AOP uses CGLib for dynamic proxies<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2</version>
  </dependency>
Copy the code

Puppy, can talk:

public class Dog {

    private String name;


    public void say(){
        System.out.println(name + "Barking! ...");
    }

    public String getName() {
        return name;
    }

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

Cut class:

Public class MyAspect {/** * Before */ / @before is the direction of the enhancements // @before is the entry point // Before() is the enhancement of legend (advice): basically, to do something. @before ()"execution(* com.zdy.. * (..) )")
    public void before(){
        System.out.println("Pre-notification...."); }}Copy the code

This class is the focus, first declaring itself as an Aspect class with @aspect, then before(). For enhancement, @before (orientation)+ pointcuts can specify the orientation of a method of a particular class. Spring configuration file:

// Enable AspectJ.<aop:aspectj-autoproxy />

    <bean id="dog" class="com.zdy.Dog" />
    <! -- Define aspect class -->
    <bean name="myAspect" class="com.zdy.MyAspect"/>
Copy the code

Then the Main method:

        ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");
        Dog dog =(Dog) ac.getBean("dog");
        System.out.println(dog.getClass());
        dog.say();
Copy the code

Output result:

class com.zdy.Dog$$EnhancerBySpringCGLIB$$80a9ee5fPre-notification.... Null is barking! .Copy the code

In plain English, throw the aspect class into the container, turn on an AdpectJ feature, and Spring AOP will locate a method of the specific class (I’m defining all methods of all classes in the com.zdy package) based on the aspect class (@before + pointcut), and then insert the enhanced Before () into it.

Here are a few AspectJ annotations like @before that Spring AOP supports:

  • @Before: This notification is executed Before the object function is executed. Note that JoinPoint is a static variable provided by Spring. Using the JoinPoint parameter, you can obtain information about the object, such as the class name, method parameter, method name, and so on. This parameter is optional.
@Before("execution(...) ")
public void before(JoinPoint joinPoint){
    System.out.println("...");
}
Copy the code
  • Post notification @afterreturning: Annotated with the @AfterRETURNING annotation, this function is executed after the target function has completed and can obtain the final return value of the target function, returnVal, which will return NULL if the target function does not return a value. Parameter names must be specified by RETURNING = “returnVal” and must be the same as those of the notification function. Please note that these parameters are optional in any notification and can be filled in if needed or not.
@AfterReturning(value="execution(...) ",returning = "returnVal")
public void AfterReturning(JoinPoint joinPoint,Object returnVal){
   System.out.println("I'm a post notification... returnVal+"+returnVal);
}
Copy the code
  • Exception notification @AfterThrowing: This notification is only raised when an exception is thrown, and Throwing declares a variable that receives exception information. Exception notification is also used for Joinpoint parameters, which can be added as needed.
@AfterThrowing(value="execution(....) ",throwing = "e")
public void afterThrowable(Throwable e){
  System.out.println("Error: MSG ="+e.getMessage());
}
Copy the code
  • Final notification @After: This notification is similar to a finally code block and will be executed no matter what the situation is as long as it is applied.
@After("execution(...) ")
public void after(JoinPoint joinPoint) {
    System.out.println("Final notice....");
}
Copy the code
  • Surrounding the notification @ Around: Around notice can perform in front of the target method can also be performed after the target method, more important is Around to inform whether can control the target method to perform, but even so, we should try to meet the requirements in the most simple way, before only in the target method executes, surrounded by prior notification should be used instead of notice. The case code, such as the first argument, must be ProceedingJoinPoint, executes the target function via the object’s proceed() method, whose return value is the return value of the surrounding advice. Similarly, the ProceedingJoinPoint object can retrieve information about the target object, such as class name, method parameters, method name, and so on
@Around("execution(...) ")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("I am surround notification before....");
    // Execute the target function
    Object obj= (Object) joinPoint.proceed();
    System.out.println("I am surround notification post....");
    return obj;
}
Copy the code

And say “…” all the time. The omitted pointcut expression, which may not be exection(..) I will not speak of it as an execution.

//scope: method scope, such as public,private,protect
//returnt-type: indicates the return value type of the method
//fully qualified-class-name: the fully qualified name of the class in which the method resides
//parameters method parameters
execution(<scope> <return-type> <fully-qualified-class-name>. * (parameters))
Copy the code
<fully-qualified-class-name>.*(parameters)
Copy the code

Note that if the package name is not exactly class-name, it stops at the package name. Use two “…” To represent any class under the package:

  • execution(* com.zdy.. * (..) ) : all methods of all classes in the com.zdy package.
  • execution(* com.zdy.Dog.*(..) ): all methods under the Dog class.

Detailed grammar, if you have the need to Google, I most commonly used is these two. Locate either by package or by concrete class.

When using a Pointcut, you can also extract an @pointcut to use:

/** * use Pointcut to define pointcuts */
@Pointcut("execution(...) ")
private void myPointcut(a){}

/** * apply the pointcut function */
@After(value="myPointcut()")
public void afterDemo(a){
    System.out.println("Final notice....");
}
Copy the code

Avoid execution multiple times in different notes…

conclusion

Well, Spring AOP implements AOP based on AspectJ annotations. It’s not really that hard, because bloggers are lazy, to talk about the main things, like pointcut expressions and there’s a lot more to say, as well as enhanced levels of sorting, such as defining multiple @before in an Aspect class, Who calls first, because the blogger thinks these knowledge points are not very important, use very little, so did not mention. After this session’s annotation-based sharing, next time I’ll cover xmL-based configuration of Spring AOP, and then some practical application scenarios. When multiple sections hit a pointcut, the order of calls at the level of the section will be mentioned. Then, the JDK dynamic proxy and CGLib dynamic proxy used by Spring AOP are briefly described. Ok, that’s all for this issue.. Over,Have a good day .