Note/大学笔记/Java/JAVA EE/Web程序设计笔记05——第三章:Spring AOP.md

6.8 KiB
Raw Blame History

第三章Spring AOP

代理:

生活中的代理: 代购(代理对象):卖化妆品 代理 韩国卖化妆品的那个商店(被代理对象):卖化妆品

代理对象和被代理对象的区别?

代理对象可以完成被代理对象的功能,除此之外,代理对象还可以添加额外功能

示例:

package com.gzh;
//韩国商店
public class Shop {
    void sell(){
        System.out.println("韩国商店卖化妆品100元");
    }
}

package com.gzh;

public class Daigou {
    private Shop shop;

    public void setShop(Shop shop) {
        this.shop = shop;
    }

    void sell(){
        System.out.println("代购要收十元小费");
        shop.sell();
        System.out.println("代购卖化妆品110元");
    }
}

package com.gzh;
//Test类模拟买化妆品的人
public class Test {
    public static void main(String[] args) {
        Daigou daigou = new Daigou();
        daigou.setShop(new Shop());
        daigou.sell();
    }
}

运行截图:

image-20220323125142944

AOP术语

AOP面向切面编程

1Aspect切面本质就是类例如MyAspect切面类完成额外功能或非核心业务功能。

2Joinpoint连接点目标方法的调用的前和后都可以称为连接点目标方法在被代理类中

3pointcut切入点就是 切入了额外功能的 连接点

4Advice通知、增强处理就是额外功能

5Target Object目标对象被代理对象。例如com.jdk.UserDaoImpl

6Proxy(代理):代理对象

7Weaving织入产生代理对象的过程例如createProxy

3.2.1 JDK动态代理

代理是谁或者说被代理对象是谁是实现了接口的类com.jdk.UserDaoImpl

额外功能所在的类? MyAspect类

如何产生代理对象? JdkProxy类

代理对象的额外功能是如何完成的?

package com.jdk;

public interface UserDao {
    void addUser();
    void deleteUser();
}
package com.jdk;
//被代理对象就是这个实现类,该类中的方法叫做目标方法
public class UserDaoImpl implements UserDao{
    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}
package com.jdk;
//额外的功能在目标方法调用前调用check_permission;在目标方法调用后条用log方法
public class MyAspect {
    public void check_permission(){
        System.out.println("模拟权限检查");
    }
    public void log(){
        System.out.println("模拟记录日志");
    }
}
package com.jdk;

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

//产生代理对象的类
public class JdkProxy implements InvocationHandler {
    private UserDao userDao;
    //方法的返回值是代理对象
    public Object createProxy(UserDao userDao){
        this.userDao=userDao;
        ClassLoader classLoader= JdkProxy.class.getClassLoader();
        Class[] clazz=userDao.getClass().getInterfaces();
        return Proxy.newProxyInstance(classLoader,clazz,this);
    }
    //invoke方法就是代理对象完成目标功能和额外功能的方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MyAspect myAspect=new MyAspect();
        myAspect.check_permission();
        Object obj = method.invoke(userDao,args);//当程序指向到此语句时,转而调用目标方法
        myAspect.log();
        return obj;
    }
}
package com.jdk;

public class JdkTest {
    public static void main(String[] args) {
        //被代理对象
        UserDao userDao = new UserDaoImpl();
        userDao.addUser();
        System.out.println("----------------");
        //生成代理对象
        JdkProxy jdkProxy = new JdkProxy();
        UserDao proxy = (UserDao) jdkProxy.createProxy(userDao);
        proxy.addUser();//当程序指向到此语句时转而执行invoke方法
    }
}

运行截图:

image-20220323150132535

3.2.2CGLIB代理

代理是谁或者说被代理对象是谁User类有两个目标方法addUser() deleteUser()

额外功能所在的类? MyAspect类

如何产生代理对象? CglibProxy类中的方法

代理对象的额外功能是如何完成的?

package com.cglib;

public class User {
    void addUser() {
        System.out.println("添加用户");
    }

    void deleteUser() {
        System.out.println("删除用户");
    }
}
package com.cglib;

//额外的功能在目标方法调用前调用check_permission;在目标方法调用后条用log方法
public class MyAspect {
    public void check_permission() {
        System.out.println("模拟权限检查");
    }

    public void log() {
        System.out.println("模拟记录日志");
    }
}
package com.cglib;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class Cglibproxy implements MethodInterceptor {
    public Object createProxy(Object target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        MyAspect myAspect = new MyAspect();
        myAspect.check_permission();
        Object obj = methodProxy.invokeSuper(proxy, args);//程序执行到此条语句时,转而执行目标方法
        myAspect.log();
        return obj;
    }
}
package com.cglib;

public class cglibTest {
    public static void main(String[] args) {
        //被代理对象
        User user = new User();
        user.addUser();
        System.out.println("---------------");
        //代理对象
        Cglibproxy cglibProxy = new Cglibproxy();
        User proxy = (User) cglibProxy.createProxy(user);
        proxy.addUser();//程序执行到此条语句时转为执行intercept方法
    }
}

运行截图如下:

image-20220324113512719

JDK代理和CGLIB代理方式的缺点

代理对象不管调用哪一种目标方法时,都会调用额外的功能。

能不能有一种手段可以使得程序员自己自由指定那些目标被调用时调用额外的功能呢Spring