[SSM-Spring Chapter 04] AOP aspect-oriented programming-proxy mode-jdbc dynamic proxy-CGLIB dynamic proxy

AOP concept

  AOP adopts a horizontal extraction mechanism, which is to extract the repeated code scattered in each method, and then apply the extracted code to the place where it needs to be executed (usually used for logging, performance statistics, security Control, transaction processing, exception handling, etc.)

AOP terminology

  1. Aspects
      (Aspect) refers to the encapsulation of cross-cutting to system functions (such as transaction processing) class.
  2. The connection point
      (Joinpoint) refers to some points in the program running, such as method calls or exceptions.
  3. Pointcuts
      pointcut (Pointcut) are those connection points in need of treatment. In Spring AOP, all method executions are connection points, and the point of entry is a description information, which modifies the connection point, and the point of entry is used to determine which connection points need to be processed.
  4. Notification (enhanced processing)
      is a piece of code added from the aspect to a specific connection point (satisfying the pointcut rule), that is, the program code to be executed at the defined pointcut. It can be understood as the method of cutting the surface after opening the surface. Therefore, notification is a concrete realization of the aspect.
  5. Introduction
      (Introduction) allows adding custom methods and attributes to existing implementation classes.
  6. Audience
      Audience (Target Object) refers to all the objects to be notified. If the AOP framework uses runtime proxy (dynamic AOP) to implement aspects, the notification object is always a proxy object.
  7. Acting
      after proxy (Proxy) is a notification to the target object, the object is dynamically created.
  8. Group into the
      group into (Weaving) is inserted into the code section on the target object, the process to generate the proxy object. According to different implementation technologies, there are three ways of AOP weaving: compiler weaving requires a special Java compiler; class loading period weaving requires a special class loader; dynamic proxy weaving, which is targeted at runtime Add notification to the class to generate subclasses. The Spring AOP framework uses dynamic proxy weaving by default, while AspectJ (a Java-based AOP framework) uses compiler weaving and class loading period weaving.



Agency model (just like the existence of an intermediary)

The proxy class is responsible for preprocessing messages for the delegated class, filtering and forwarding the messages, and performing subsequent processing after the message is executed by the delegated class. (Add additional features)

(Virtual) proxy

  Virtual agents are representative of objects that are expensive to create . Virtual agents often don't create an object until we really need it. When the object is created before and when it is being created, the virtual agent acts as a stand-in for the object. After the object is created, the proxy delegates the request directly to the object.
Insert picture description here



Static proxy

  You need to explicitly implement the same interface as the target object class (RealSubject) , and the proxy class has been created before the program runs .

Case realization

  1. Create the interface and implementation of the proxy class
public interface Math {
    
    
    public int jia(int a, int b);//加
    public int jian(int a, int b);//减
}
public class MathImpl implements Math{
    
    

    public int jia(int a,int b){
    
    
        return a+b;
    }
    public int jian(int a,int b){
    
    
        return a-b;
    }
}
  1. Create tool classes to implement common methods
public class Tools {
    
    

    public void check(){
    
    
        System.out.println("权限检查......");
    }
    public void log(){
    
    
        System.out.println("日志记录......");
    }

}

  1. Create proxy class
public class MathProxy implements Math {
    
    

//    MathImpl mathImpl = new MathImpl();  //业务逻辑
//    Tools tools = new Tools();  //工具类
    MathImpl mathImpl;  //业务逻辑
    Tools tools;  //工具类

//    public MathProxy(){}
    public MathProxy(MathImpl mathImpl, Tools tools) {
    
    
    	//在构造器中直接初始化了
        this.mathImpl = mathImpl;
        this.tools = tools;
    }

    @Override
    public int jia(int a, int b) {
    
    
        tools.check();
        int result = mathImpl.jia(a,b);
        tools.log();
        return result;
    }

    @Override
    public int jian(int a, int b) {
    
    
        tools.check();
        tools.log();
        return mathImpl.jian(a,b);
    }
}
  1. Create test class
public class Test {
    
    

    public static void main(String[] args) {
    
    
        /* 被代理对象--业务类 数学计算类 */
        MathImpl mathImpl = new MathImpl();
		//创建工具类
        Tools tools = new Tools();
        
//      代理对象
        Math math = new MathProxy(mathImpl,tools);
        int result1 = math.jia(2,6);
        System.out.println(result1);
        
        int result2 = math.jia(3,2);
		System.out.println(result2);
    }
}

  1. operation result

Insert picture description here



Dynamic proxy (JDK and CGLIB dynamic proxy are commonly used in Spring AOP-now generally use aspectj)

  There is no need to explicitly implement the same interface as the target object class (RealSubject), but postpone this implementation until the program is run by the JVM. Dynamic agents are created when needed, not in advance .

The main difference between JDK and CGLIB dynamic proxy:

JDK dynamic proxy can only proxy the interface methods of the class that implements the interface.
CGLIB dynamic proxy implements proxy based on inheritance, so it cannot proxy final classes, private methods, and static methods.

The default strategy used by the proxy in Spring AOP is:

If the target object implements the interface, JDK dynamic proxy is used by default.
If the target object does not implement the interface, CgLib is used for dynamic proxy.
If the target object implements the interface and CgLib is forced to proxy, then CgLib is used for dynamic proxy.


1. JDK dynamic proxy implements Spring AOP

  JDK dynamic proxy is the method provided by the java.lang.reflect.* package. It must use an interface to generate proxy objects. Therefore, for classes that use business interfaces, Spring uses JDK dynamic proxy to implement AOP by default .
  In Spring, JDK dynamic proxy is used by default to implement AOP programming . Using org.springframework.aop.framework.ProxyFactoryBean to create a proxy is the most basic way to implement Spring AOP.

Case realization

  1. Create the interface and implementation class of the proxy class
public interface UserDao {
    
    
    public void save(String name);  //保存
    public void delete();           //删除
}
//被代理类
public class UserDaoImpl implements UserDao{
    
    
    @Override
    public void save(String name) {
    
    
        System.out.println("保存用户成功 :"+name);
    }

    @Override
    public void delete() {
    
    
        System.out.println("删除用户成功:");
    }
}
  1. Create an aspect class (public method)
//切面类:定义公共方法
public class MyAspect {
    
    
    public void check(){
    
    
        System.out.println("check user......正在查找用户");
    }

    public void log(){
    
    
        System.out.println("logging.....正在记录日志");
    }
}
  1. Create proxy class
//代理类
public class MyProxy implements InvocationHandler {
    
    

    private UserDao userDao;    //被代理类
    private MyAspect myAspect;  //切面类 -- 定义公共方法

    public MyProxy(UserDao userDao, MyAspect myAspect) {
    
    
        this.userDao = userDao;
        this.myAspect = myAspect;
    }

    //创建代理对象
    public Object create(){
    
    
        ClassLoader classLoader = userDao.getClass().getClassLoader();
//      Class<?>[] interfaces  被代理对象的实现接口
        Class<?>[] interfaces = userDao.getClass().getInterfaces();
        UserDao proxy = (UserDao) Proxy.newProxyInstance(classLoader,interfaces,this);
        System.out.println("创建代理对象create");
        return proxy;
    }

//    调用方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
//        织入 advice 加入到 被代理对象方法之前或之后
//        method就是调用的被代理对象的方法
        String methodName = method.getName();
//        Object 被代理对象
//        调用方法
        System.out.println("调用invoke方法");
        myAspect.check();//调用切面方法
        method.invoke(userDao,args);//userDaoImpl.save(参数)
        myAspect.log();//调用切面方法
        return null;
    }
}
  1. Create test class
public class Test {
    
    
    public static void main(String[] args) {
    
    
//      被代理类
        UserDao userDao = new UserDaoImpl();
//      切面
        MyAspect myAspect = new MyAspect();

        //创建代理类  参1:被代理类  参2:切面(公共方法)
        MyProxy myProxy = new MyProxy(userDao,myAspect);
        //通过代理类来创建实例 - 代理对象
        UserDao proxy = (UserDao)myProxy.create();
        proxy.save("GF_浪夏一学");
        proxy.delete();
    }
}
  1. operation result

Insert picture description here


2. CGLIB dynamic proxy implements Spring AOP

  CGLIB (Code Generation Library) is a high-performance open source code generation package that uses very low-level bytecode technology to generate a subclass of the specified target class, and enhance the subclass. The JAR package required by CGLIB has been integrated in the Spring Core package, and there is no need to import the JAR package separately

Case realization

  1. Create a proxy class (target class)
public class UserService {
    
    
    public void save(){
    
    
        System.out.println("save service ......");
    }
    public void delete(){
    
    
        System.out.println("delete service ......");
    }
}
  1. Create an aspect class (public method)
public class MyAspect {
    
    

    public void check(){
    
    
        System.out.println("check方法......检查包");
    }

    public void log(){
    
    
        System.out.println("logging方法......记录日志");
    }
}
  1. Create proxy class
public class MyProxy<T> implements MethodInterceptor {
    
    

    private T byProxy;          //被代理类
    private MyAspect myAspect;  //切面

    public MyProxy(T byProxy, MyAspect myAspect) {
    
    
        this.byProxy = byProxy;
        this.myAspect = myAspect;
    }

//    创建代理对象
    public T create(){
    
    
        // 通国Enhancer创建代理类 ----  Proxy
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(byProxy.getClass());
        enhancer.setCallback(this);//实现MethodInterceptor接口的对象,就是当前对象
        T proxy = (T)enhancer.create();
        return proxy;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
    

//        Method method,调用的被代理对象方法
        String methodName = method.getName();
        if(methodName.equals("save")){
    
    
            myAspect.check();
            method.invoke(byProxy,objects);
            myAspect.log();
        }
        if(methodName.equals("delete")){
    
    
            myAspect.check();
            method.invoke(byProxy,objects);
            myAspect.log();
        }
        return null;
    }
}

  1. Create test class
public class CGLIBTest {
    
    
    public static void main(String[] args) {
    
    
//       被代理对象
        UserService userService = new UserService();
        MyAspect myAspect = new MyAspect();

        //创建代理对象
        MyProxy myProxy = new MyProxy(userService,myAspect);
        //通过代理类创建被代理对象
        UserService service = (UserService)myProxy.create();

        //调用方法
        service.save();
        service.delete();
    }
}
  1. operation result
    Insert picture description here

Guess you like

Origin blog.csdn.net/qq_40542534/article/details/108683231