2, AOP of spring 5 framework

Keywords: Spring JDK Java xml

AOP

AOP (concept)

(1) Face to face programming (aspect), AOP can isolate all parts of business logic, so that
The coupling degree between each part of business logic is reduced, the reusability of program is improved, and the efficiency of development is improved.
(2) Popular Description: add new functions to the trunk function without modifying the source code
(3) Use examples to illustrate AOP

Using dynamic agent in AOP bottom layer

1. What is AOP

(1) There are two kinds of dynamic agents

  • The first case has an interface, using JDK dynamic agent
    1. Create interfaces to implement class proxy objects and enhance class methods
  • In the second case, CGLIB dynamic agent is used
    1. Create proxy objects of subclasses and enhance methods of classes

AOP (JDK dynamic agent)

1. Use JDK dynamic Proxy to create Proxy objects using methods in Proxy class


(1) Call the newProxyInstance method

Method has three parameters:
First parameter, classloader
The second parameter is the class where the enhancement method is located. The interface implemented by this class supports multiple interfaces
The third parameter is to implement the InvocationHandler interface, create the proxy object, and write the enhanced part

2. Write JDK dynamic agent code

(1) Create interface, define method

package com.company.jdkaop;
public interface UserDao {
    public void insert();
    public Boolean update();
}

(2) Create interface implementation class and implementation method

package com.company.jdkaop;

public class UserDaoImpl implements UserDao {
    @Override
    public void insert() {
                System.out.println("Executed insert method");
    }

    @Override
    public Boolean update() {
        return null;
    }
}

(3) Using Proxy class to create interface Proxy object

package com.company.jdkaop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkProxy {
    public static void main(String[] args) {
        //Create interface implementation class proxy object
        Class[] interfaces = {UserDao.class};
        UserDaoImpl userDao = new UserDaoImpl();
        UserDao o = (UserDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
        o.insert();
    }
}

//Create proxy object code
class UserDaoProxy implements InvocationHandler {
    //1. Pass the created proxy object to
    //Parametric construction transfer
    private Object obj;
    public UserDaoProxy(Object obj){
        this.obj = obj;
    }

    //Enhanced logic
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method");

//        Method is executed
        Object res = method.invoke(obj, args);

        System.out.println("After method");
        //Return results
        return res;
    }
}

AOP (terminology)

1. Connection point

Which methods in the class can be enhanced and become join points

2. Entry point

The approach that is actually enhanced is called the pointcut

3. Notification (enhanced)

Actually enhanced logical part

4. Notification type
  • Pre notification (before method)
  • Post notification (after method)
  • Orbit notification (before and after method)
  • Exception notification (method exception)
  • Final notification (after method execution, before return)
5. Section

The process of applying notifications to pointcuts

AOP operation

1. Spring framework is generally based on AspectJ to implement AOP operations

(1) AspectJ is not a part of Spring. It is an independent AOP framework. AspectJ is generally used together with spinning framework for AOP operation

2. AOP operation based on AspectJ

(1) Implementation of configuration file based on xml
(2) Implementation based on annotation

3. Introduce AOP related dependency into project engineering

4. Pointcut expression

(1) Pointcut expression function: know which method in which class to enhance
(2) Grammatical structure:
execution([permission modifier] [return type] [class full path] Method name )

Example 1: Yes com.company.dao add in the. Bookdao class to enhance
execution(* com.company.dao.BookDao.add(...))

Example 2: Yes com.company.dao All methods in the. Bookdao class are enhanced
execution(* com.company.dao.BookDao.* (...))

Example 3: Yes com.company.dao All classes and methods in the package are enhanced
execution(* com.company.dao.. (...))

AOP operation (AspectJ annotation)

1. Create a class and define methods in the class
package com.company.Aspectj;

public class User {
    public void add(){
        System.out.println("add to");
    }
}

2. Create enhancement class (write enhancement logic)

(1) In the enhanced class, create methods to represent different notification types

package com.company.Aspectj;

public class UserProxy {
    public void before(){
        System.out.println("Before method");
    }
}

3. Configure for notifications
<!--    Enable annotation scanning-->
<context:component-scan base-package="com.company"></context:component-scan>

(2) Using annotations to create User and UserProxy objects

@Component

(3) Add annotation @ Aspect to the enhanced class

@Component
@Aspect  //Build proxy object
public class UserProxy {
    public void before(){
        System.out.println("Before method");
    }
}

(4) Turn on the build agent object in the spring configuration file

<! -- turn on Aspect generation proxy object -- >
 <aop:aspectj-autoproxy></aop:aspectj-autoproxy
4. Configure different types of notifications

(1) In the enhanced class, notice type annotation is added as the notice method, and pointcut expression configuration is used

package com.company.Aspectj;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect  //Build proxy object
public class UserProxy {


    //Before advice 
    @Before(value = "execution(* com.company.Aspectj.User.add(..))")
    public void before(){
        System.out.println("Before advice ");
    }

    //Post notice
    @AfterReturning(value = "execution(* com.company.Aspectj.User.add(..))")
    public void afterReturning(){
        System.out.println("Post notice");
    }

    ////Final notice
    @After(value = "execution(* com.company.Aspectj.User.add(..))")
    public void after(){
        System.out.println("Final notice");
    }

    //Exception notification
    @AfterThrowing(value = "execution(* com.company.Aspectj.User.add(..))")
    public void AfterThrowing(){
        System.out.println("Exception notification");
    }

    //Around Advice 
    @Around(value = "execution(* com.company.Aspectj.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("Before wrapping");
        //Enhanced method execution
        proceedingJoinPoint.proceed();

        System.out.println("After orbit");
    }

}

5. Same pointcut extraction
package com.company.Aspectj;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect  //Build proxy object
public class UserProxy {

    //Extraction entry point
    @Pointcut(value = "execution(* com.company.Aspectj.User.add(..))")
    public void point(){

    }


    //Before advice 
    @Before(value = "point()")
    public void before(){
        System.out.println("Before advice ");
    }

    //Post notice
    @AfterReturning(value = "point()")
    public void afterReturning(){
        System.out.println("Post notice");
    }

    ////Final notice
    @After(value = "point()")
    public void after(){
        System.out.println("Final notice");
    }

    //Exception notification
    @AfterThrowing(value = "point()")
    public void AfterThrowing(){
        System.out.println("Exception notification");
    }

    //Around Advice 
    @Around(value = "point()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("Before wrapping");
        //Enhanced method execution
        proceedingJoinPoint.proceed();

        System.out.println("After orbit");
    }

}

6. There are multiple enhancement classes and the same method for enhancement. Set the priority of enhancement classes

@Order(1)

7. Full use of annotation development

(1) To create a configuration class, you do not need to create an xml configuration file

7,Full use of annotation development (1) to create configuration classes, no need to create xml configuration file 
@Configuration
@ComponentScan(basePackages = {"com.atguigu"})
@EnableAspectJAutoProxy(proxyTargetClass = true) <!--    open Aspect Build proxy object-->

public class ConfigAop {
}

AOP operation (AspectJ configuration file)

1. Create two classes, enhanced class and enhanced class, and create methods
2. Create two class objects in the spring configuration file

3. Configuring pointcuts in the spring configuration file
<!--    to configure aop enhance-->
    <aop:config>
<!--        Configuration entry point-->
        <aop:pointcut id="userpointcut" expression="execution(* com.company.Aspectj.User.add(..))"/>
<!--        Configure facets-->
        <aop:aspect ref="userProxy">
<!--            Enhance in specific ways-->
            <aop:after method="beforeByXml" pointcut-ref="userpointcut"></aop:after>
        </aop:aspect>
    </aop:config>

Using aop to dynamically set data source in project

1. Data source switching interceptor

<bean id="dataSourceInterceptor" class="com.liang.commons.db.DataSourceInterceptor"></bean>

2. AOP configuration

<aop:config expose-proxy="true" proxy-target-class="true">
      <aop:aspect ref="dataSourceInterceptor">
            <!-- Data source 1 tangent point (basic module) -->
            <aop:pointcut
                    expression="(execution(* com.sage.system.controller.supervision..*.*(..)))"
                    id="pointcut1"/>
            <aop:around method="dataSource1Interceptor" pointcut-ref="pointcut1"/>
        </aop:aspect>
        <aop:aspect ref="dataSourceInterceptor">

            <!-- Data source 2 tangent point (basic module) -->
            <aop:pointcut
                    expression="(execution(* com.sage.system.controller.zlreport..*.*(..)))"
                    id="pointcut2"/>
            <aop:around method="dataSource2Interceptor" pointcut-ref="pointcut2"/>
        </aop:aspect>
    </aop:config>
3,Data source switching interceptor code
public class DataSourceInterceptor {

    protected Logger logger = LogManager.getLogger(getClass());

    public Object dataSource1Interceptor(ProceedingJoinPoint point) throws Throwable {
        //Get database content from ShiroUser (username + URL + password + driverclass)
        List<Programsys> collect = UserInfo.getShiroUserInfo().getProgramsys().stream().filter(item -> {
            return item.getServername().equals(DbConstant.DATABASES_SUPERVISION_NAME);
        }).collect(Collectors.toList());
        try {
            //Create DataSourceBean
            DataSourceBean dataSourceBean = new DataSourceBean(new DataSourceBean.DataSourceBeanBuilder(collect.get(0).getBeanname(),
                    collect.get(0).getServerip(), collect.get(0).getPort(),collect.get(0).getServername(),
                    collect.get(0).getUsername(), collect.get(0).getPassword()));
            //set up
            DataSourceContext.setDataSource(dataSourceBean);
            logger.info("*****************Switch to 1 system data source");

            //Execute enhanced method
            Object result = point.proceed();

            //Set data source as default
            DataSourceContext.toDefault();

            //Return results
            return result;

        } finally {
            //Set data source as default
            DataSourceContext.toDefault();
        }
    }



    public Object dataSource2Interceptor(ProceedingJoinPoint point) throws Throwable {
        List<Programsys> collect = UserInfo.getShiroUserInfo().getProgramsys().stream().filter(item -> {
            return item.getServername().equals(DbConstant.DATABASES_ZLREPORT_NAME);
        }).collect(Collectors.toList());
        try {
            DataSourceBean dataSourceBean = new DataSourceBean(new DataSourceBean.DataSourceBeanBuilder(collect.get(0).getBeanname(),
                    collect.get(0).getServerip(), collect.get(0).getPort(),collect.get(0).getServername(),
                    collect.get(0).getUsername(), collect.get(0).getPassword()));
            DataSourceContext.setDataSource(dataSourceBean);
            logger.info("*****************Switch to 2 system data source");
            Object result = point.proceed();
            DataSourceContext.toDefault();
            return result;
        } finally {
            DataSourceContext.toDefault();
        }
    }

}

I don't think it's right to switch.................................................................

Posted by michaelk46 on Sat, 06 Jun 2020 00:12:00 -0700