编程知识 cdmana.com

Catalog

Why to achieve AOP

Hard encoding

OOP

AOP

AspectJ

spring AOP

Annotation based spring aop Development

be based on XMl Development of

Spring AOP Implementation process

AOP Realization principle

JDK A dynamic proxy

CGLib A dynamic proxy


 

What is? AOP

Section oriented programming It's an idea , Its programming idea is to extract the code distributed in different business but with the same function from the business logic , Packaged as a separate module , These separate modules are called facets , For example, authority authentication 、 journal 、 Business 、 Context processing 、 exception handling 、 Lazy loading 、 buffer .

Facing the section The purpose is to decoupling close , Separate the various concerns of the system , Handle the business process ( Core concerns ) And parts that have little to do with the mainstream process ( Crosscutting concerns ) Separate , Single responsibility , We have a special job .

Why to achieve AOP

We know that the implementation of logging is based on AOP. Log the access method , In fact, there are many ways , So why did you choose AOP The way ? Let's take a look at

Hard encoding

Hard coding solves the problem of logging , But the processing code is the same , Severe coupling , Once it needs to be modified , And there are thousands of ways , So it's going to be a huge project , Engineers must not be able to stand it , Then use OOP To improve the way .

OOP

This is a OOP Two ways of implementing ,OOP The core idea is to encapsulate , Inherit .

The first way is to extract the log processing code into separate classes . When this is modified , Just adjust the code in a separate class , Avoid the problem of digging graves everywhere caused by hard coding , Greatly reduces the complexity of maintenance .

The second way is through inheritance , Just put the same extracted code into a class , Other categories ( Subclass ) Get the same code by inheritance .

Through the two methods above , Code redundancy has been solved . But as software system development becomes more and more complex , More and more code , Our vision is , The core business code is the core business code , But in both ways , Often lead to core business code mixed with some unrelated special business , Like logging 、 Transaction control 、 Error information monitoring and so on . This will cause code confusion 、 Dispersed 、 Redundancy and so on . So how to achieve our vision , Separate the core business code from the code of other peripheral operations , These peripheral modules can be hot pluggable without intruding into the core module ? That's it AOP 了 .

AOP

Our goal is to see the peripheral business as a separate focus , They can be used in time when they are needed and need not be integrated into the core modules in advance . Each concern is separated from the core business module , As a separate function , Crosscutting several core business modules . This level of abstraction technology is called AOP Section oriented programming . And these separate concerns , It's called crosscutting concerns .

AOP There are many kinds of implementation technologies of ,AspectJ It can be done with Java Seamless docking .

AspectJ

aspectJ It's a java Realized AOP frame , and spring AOP The implementation principle is different , But the function is similar . What we use directly in development is spring AOP, understand aspectJ Can help to understand spring AOP.

1、 Use aspectJ Technical realization AOP When ,aspect It is a statement. section Class keyword , And the file suffix is .aj, Meaning and .class similar .

2、 It's used inside the section pointcut Defined the pointcut , Tangent point It's the methods that need to reference facets , Methods that need to reference facets are also known as The target method .

3、 Use before()、after()、after returning()、after throwing()、around() Define notification , notice The functions that need to be executed before and after the target method .

4、 therefore , Facet is the combination of pointcut and notification , Form a separate structural worker for subsequent use .

5、 The process of referring facets to the target method is called Weaving , In other words, these methods can cut into the notification code before and after execution , These target methods are collectively referred to as Connection point , Tangent point It's a collection of join points .

aspectJ The use of :

/**
 *  Section class 
 */
public aspect MyAspectJDemo {
    /**
     *  Defining cut-off points , Logging pointcuts 
     */
    pointcut recordLog():call(* HelloWord.sayHello(..));

    /**
     *  Defining cut-off points , Authority verification ( In actual development, logs and permissions are usually placed in different aspects , This is just for the sake of demonstration )
     */
    pointcut authCheck():call(* HelloWord.sayHello(..));

    /**
     *  Define pre notice !
     */
    before():authCheck(){
        System.out.println("sayHello Verify permissions before method execution ");
    }

    /**
     *  Define post notification 
     */
    after():recordLog(){
        System.out.println("sayHello Log after method execution ");
    }
}

Weaving

above-mentioned AspectJ and spring AOP The implementation principle of is different , It is embodied in weaving . Weaving represents the process of applying facets to objective functions . For this process , It is generally divided into dynamic weaving and static weaving , The way of dynamic weaving is to dynamically weave the enhanced code into the target class at runtime , This is often done through dynamic proxy technology , Such as Java JDK Dynamic proxy for (Proxy, The bottom layer is realized by reflection ) perhaps CGLIB Dynamic proxy for ( The bottom layer is implemented by inheritance ),Spring AOP It's based on runtime enhanced agent technology , This will be analyzed later .

Here we mainly focus on the analysis of static weaving ,ApectJ It's static weaving .ApectJ It mainly uses compile time weaving , Use during this period AspectJ Of acj compiler ( similar javac) hold aspect Class to class After bytecode , stay java Target class is weaved in at compile time , First compile aspect Class recompile the target class .

About ajc compiler , It's a way to recognize aspect Syntax compiler , It's using java language-written , because javac It doesn't recognize aspect grammar , There is a ajc compiler , Be careful ajc Compilers can also compile java file .

spring AOP

AspectJ stay AOP Depending on the special compiler (ajc compiler ), Implement compiler weaving .Spring To avoid that , Turn to the implementation principle of dynamic agent technology to build Spring AOP Internal mechanism ( Dynamic weaving ), This is the AspectJ( Static weaving ) The fundamental difference . stay AspectJ 1.5 after , introduce @Aspect Formal annotation style development ,Spring And very quickly followed up this way , introduce spring-aspects jar package , have access to AspectJ Annotations .

spring AOP The concept of and the one introduced above aspectJ The concept is the same , Such as tangent point (pointcut) Define the target function that requires notification to be applied , Notification is the body of functions that need to be applied to the objective function , section (Aspect) It is the combination of notice and cut-off point . Weaving (weaving), take aspect Class applied to the objective function ( class ) The process of , It's just Spring AOP The bottom layer is implemented by dynamic proxy technology .

Annotation based spring aop Development

Define the facet class

/**
 *  Section class 
 * @author lfy
 * 
 * @Aspect:  tell Spring The current class is a faceted class 
 *
 */
@Aspect
public class LogAspects {
	
	// Extract common pointcut expressions 
	//1、 This class quotes 
	//2、 Other facet references 
	@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
	public void pointCut(){};
	
	//@Before Cut in before the target method ; Pointcut expression ( Specify which method to cut in )
	//@Before("public int com.atguigu.aop.MathCalculator.*(..))
	// After extracting the common pointcut expression 
	@Before("pointCut()")
	//JoinPoint  Get method name 、 Parameters 、 Return value 、 Abnormal information 
	public void logStart(JoinPoint joinPoint){
		Object[] args = joinPoint.getArgs();
		System.out.println(""+joinPoint.getSignature().getName()+" function ...@Before: The parameter list is :{"+Arrays.asList(args)+"}");
	}
	
	@After("com.atguigu.aop.LogAspects.pointCut()")
	public void logEnd(JoinPoint joinPoint){
		System.out.println(""+joinPoint.getSignature().getName()+" end ...@After");
	}
	
	//JoinPoint It must appear in the first place in the parameter list 
	@AfterReturning(value="pointCut()",returning="result")
	public void logReturn(JoinPoint joinPoint,Object result){
		System.out.println(""+joinPoint.getSignature().getName()+" Normal return ...@AfterReturning: Running results :{"+result+"}");
	}
	
	@AfterThrowing(value="pointCut()",throwing="exception")
	public void logException(JoinPoint joinPoint,Exception exception){
		System.out.println(""+joinPoint.getSignature().getName()+" abnormal ... Abnormal information :{"+exception+"}");
	}

}

1、@Aspect Annotations define facet classes

2、@Pointcut The pointcut function is defined , Notification type annotations can also define pointcut functions directly , Such as @Before("public int com.atguigu.aop.MathCalculator.*(..))

3、@Before、@After、@AfterReturning、@AfterThrowing、@Around Five types of notification are defined .

4、execution It's the pointcut indicator , The pointcut indicator identifies which target methods the notification applies to .

4.1、execution Represents the method signature expression : If you want to filter by method signature , keyword execution Can help us , The syntax is as follows :

//scope : Method scope , Such as public,private,protect
//returnt-type: Method return value type 
//fully-qualified-class-name: The fully qualified name of the class in which the method resides 
//parameters  Method parameter 
execution(<scope> <return-type> <fully-qualified-class-name>.*(parameters))

except execution, There are other pointcut indicators

4.2、 Type signature expression : For convenience of type ( Such as interface 、 Class name 、 Package name ) Filtration method ,Spring AOP Provides within keyword , The syntax is as follows :

within(<type name>)

// matching com.zejian.dao All methods in all classes in the package and its children 
@Pointcut("within(com.zejian.dao..*)")
// matching UserDaoImpl Class 
@Pointcut("within(com.zejian.dao.UserDaoImpl)")
// matching UserDaoImpl Class and all methods in its subclasses 
@Pointcut("within(com.zejian.dao.UserDaoImpl+)")

4.3、 wildcard

 .. : Match any number of parameters in the method definition , It also matches any number of packages in the class definition

+ : Match any subclass of a given class

* : Match any number of characters


4.4、@annotation(com.zejian.spring.MarkerMethodAnnotation) : Method filtering based on applied annotations

// Match using MarkerAnnotation Method of annotation ( Attention is the method )
@Pointcut("@annotation(com.zejian.spring.annotation.MarkerAnnotation)")
private void myPointcut5(){}

 

Define business logic classes

public class MathCalculator {
	
	public int div(int i,int j){
		System.out.println("MathCalculator...div...");
		return i/j;	
	}

}

Turn on AOP And add facet classes and business logic classes to the container

@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
	 
	// The business logic class is added to the container 
	@Bean
	public MathCalculator calculator(){
		return new MathCalculator();
	}

	// Facet classes are added to the container 
	@Bean
	public LogAspects logAspects(){
		return new LogAspects();
	}
}

@EnableAspectJAutoProxy The comment means open AOP, After opening spring The container will try to identify the tape automatically @Aspect Of Bean

@Configuration+@Bean It means that you will Bean Add to container

Test class

@Test
	public void test01(){
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
		
		//1、 Don't create your own objects 
//		MathCalculator mathCalculator = new MathCalculator();
//		mathCalculator.div(1, 1);

        // Creating Bean In the process of , If it is judged that Bean Need to enhance , The proxy object will be created 
		MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);	
        // Here mathCalculator Object is already a proxy object     
		mathCalculator.div(1, 0);
		
		applicationContext.close();
	}

be based on XMl Development of

After the previous analysis, annotation based development is the most common in daily applications , Even so, it is necessary for us to understand that based on xml Formal Spring AOP Development , We also need to define the above facet class , Then activate the section function , Configure the facet class as Bean、 Definition, notification, etc. need to be in xml Configuration in file .

<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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--<context:component-scan base-package=""-->
    <!--  start-up @aspectj Automatic agent support for -->
    <aop:aspectj-autoproxy />

    <!--  Define the target object  -->
    <bean name="productDao" class="com.zejian.spring.springAop.dao.daoimp.ProductDaoImpl" />

    <!--  Define facets  -->
    <bean name="myAspectXML" class="com.zejian.spring.springAop.AspectJ.MyAspectXML" />
    <!--  To configure AOP  section  -->
    <aop:config>
        <!--  Defining tangent functions  -->
        <aop:pointcut id="pointcut" expression="execution(* com.zejian.spring.springAop.dao.ProductDao.add(..))" />

        <!--  Define other tangent functions  -->
        <aop:pointcut id="delPointcut" expression="execution(* com.zejian.spring.springAop.dao.ProductDao.delete(..))" />

        <!--  Define notification  order  Define priority , The lower the value, the higher the priority -->
        <aop:aspect ref="myAspectXML" order="0">
            <!--  Define notification 
            method  Specify the notification method name , Must be with MyAspectXML The same in 
            pointcut  Specify the tangent function 
            -->
            <aop:before method="before" pointcut-ref="pointcut" />

            <!--  The rear notice   returning="returnVal"  Define the return value   Must be the same as the name declared in the class -->
            <aop:after-returning method="afterReturn" pointcut-ref="pointcut"  returning="returnVal" />

            <!--  Surrounding the notification  -->
            <aop:around method="around" pointcut-ref="pointcut"  />

            <!-- Abnormal notice  throwing="throwable"  Specifies the exception notification error message variable , Must be the same as the name declared in the class -->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="throwable"/>

            <!--
                 method :  Method of notification ( Final notice )
                 pointcut-ref :  The pointcut method to which notification applies 
                -->
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>
</beans>

Spring AOP Implementation process

  1. Whether it's annotation implementation or xml Realization way , Turn on AOP Function is our entry point , For example, annotation ,@EnableAspectJAutoProxy Turn on AOP function
  2. @EnableAspectJAutoProxy  Will register a component in the container  AnnotationAwareAspectJAutoProxyCreator, It's a post processor , The primary function of this post processor is to create proxy objects 
  3. IOC Container creation process
    1. registerBeanPostProcessors() Register the post processor ; establish AnnotationAwareAspectJAutoProxyCreator object 
    2. finishBeanFactoryInitialization() Initialize the remaining single instance bean
      1.  Create business logic components and aspect components 
      2. AnnotationAwareAspectJAutoProxyCreator The creation process of interception component 
      3.  After the component is created , Determine if components need to be enhanced 
        1.  yes : Face to face notification method , Pack it as an intensifier (Advisor); Create a proxy object for the business logic component (cglib)
  4.  Execution target method :
    1.  The proxy object executes the target method 
    2. CglibAopProxy.intercept() To intercept  ;
      1.  Get the blocker chain of the target method ( The enhancer is packaged as an interceptor MethodInterceptor)
      2.  Using the chain mechanism of interceptors , Enter each interceptor in turn to execute ;
      3.  effect :
        1.  Normal execution : Pre notice -》 The target method -》 The rear notice -》 Return to inform 
        2.  Something unusual happened : Pre notice -》 The target method -》 The rear notice -》 Abnormal notice 

AOP Realization principle

spring AOP The principle of the implementation of the previous analysis , We talked about Spring AOP The principle of implementation is dynamic proxy technology based on dynamic weaving , and AspectJ It's static weaving , And dynamic proxy technology is divided into Java JDK Dynamic proxy sum CGLIB A dynamic proxy , The former is based on reflection technology , The latter is based on inheritance mechanism .

In the process above , We can find that , In judging the present bean Whether or not to enhance the time , If enhancement is needed , The proxy object will be created , At the time of creation, if the current bean Implement the interface , Will use jdk Dynamic , If the interface is not implemented , Will use cglib A dynamic proxy .

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            // Use jdk Dynamic agent implementation 
            return new JdkDynamicAopProxy(config);
        } else {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
            } else {
                // Use cglib Dynamic agent implementation 
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

JDK A dynamic proxy

jkd The implementation logic and proxy class creation process can refer to my previous blog :jkd A dynamic proxy

AOP The logical judgment for creating a proxy object is : If the surrogate class has an implementation interface , Will use jdk A dynamic proxy . therefore jdk The prerequisite of dynamic proxy is that the target object must have an interface . The reason is to get from the container bean when , If it is judged that bean Need to enhance , The interface to the target object is obtained through reflection , Dynamic proxy technology can create proxy objects of the same type as the target object . After getting the proxy object , The target method can be executed by the proxy object .

CGLib A dynamic proxy

cglib The implementation process of dynamic proxy can also refer to my previous blog :cglib A dynamic proxy

AOP The logical judgment for creating a proxy object is : If the class being proxied does not implement an interface , Will use cglib A dynamic proxy . So you can see that ,cglib Dynamic proxies don't need to and jdk Dynamic proxy is the same , The prerequisite must implement the interface .

cglib Dynamic proxy sum JDk The difference between dynamic proxies is that cglib Dynamic proxies are implemented by inheriting the surrogate class , The generated dynamic proxy class is a subclass of the proxy class , Then the proxy is implemented by rewriting the business method .

Although the proxy class does not need to implement an interface to implement a dynamic proxy , however CGLibProxy The proxy class needs to implement a method interceptor interface MethodInterceptor And rewrite intercept Method , similar JDK Dynamic proxy InvocationHandler Interface , It is also understood as a callback function , Similarly, every time a method of a proxy object is called ,intercept Methods will be called , Using this method, we can dynamically enhance the method before and after execution at runtime .

 

spring AOP That's the end of the implementation of . There is something wrong with the above , Thank you for your correction .

版权声明
本文为[Wooden pine cat]所创,转载请带上原文链接,感谢

Tags spring aop
Scroll to Top