注:SpringAOP默认使用的是JDK Proxy动态代理,如需CGLIB需要配置
    配置文件开启CGLIB:

    1. <aop:config proxy-target-class="true" /> 默认falce JDKProxy
    2. 注解开启
    3. <aop:aspectj-autoproxy proxy-target-class="true" />

    注解开启:
    @EnableAspetJAutoProxy(proxyTargetClass = true)

    JDK Proxy:

    • 在不改变目标对象方法的情况下对方法进行增强
    • 组成:
      • 被代理对象:真实对象
      • 代理对象:内存中的一个对象
    • 要求:
      • 代理对象必须和被代理对象实现相同接口
    • 实现:
      • Proxy.newProxyInstance():
        • 参数1:和被代理对象使用相同类加载器:被代理对象.getClass().getClassLoader()
        • 参数2:Class数组(和被代理对象使用相同接口),new Class[]{被代理对象接口.class}
        • 参数3:代理规则 new InvocationHandler()匿名内部内
    1. public class Test {
    2. public static void main(String[] args) {
    3. final Student student = new Student();
    4. /*
    5. 类加载器:和被代理对象使用相同的类加载器
    6. 接口类型的class数组:和被代理对象使用相同的接口
    7. 代理规则:完成代理增强的功能
    8. */
    9. StudentInterface proxyStu = (StudentInterface) Proxy.newProxyInstance(student.getClass().getClassLoader(), new Class[]{StudentInterface.class}, new InvocationHandler() {
    10. /*
    11. 执行Student类中所有方法都会经过invoke方法
    12. method:被代理对象的方法
    13. args:被代理对象传递的参数
    14. */
    15. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    16. if(method.getName().equals("study")) {
    17. System.out.println("测试测试");
    18. return null;
    19. }else {
    20. return method.invoke(student,args);
    21. }
    22. }
    23. });
    24. proxyStu.eat("米饭");
    25. proxyStu.study();
    26. }
    27. }

    代理规则:
    所有方法都会经过代理规则的invoke方法,可在方法内对当前执行的方法进行判断

    ps:根据自己写的方法,动态生成一个内存中的地址,执行时会先调用自己写的方法返回给动态代理,在invoke这里被拦截

    —————————————————————————————————————————————————————————————
    案例:
    原始方法

    1. public class UserServiceImpl implements UserService {
    2. @Override
    3. public void save() {
    4. System.out.println("测试一");
    5. }
    6. }

    Proxy类:

    1、首先new一个InvocationHandler对象(参数1:原始对象,参数2:原始对象接口数组,参数3:规则)
    参数1:使用ClassLoader cl = userService.getClass().getClassLoader();获取原始对象
    参数2:使用Class[] classes = userService.getClass().getInterfaces(); getInterfaces获取原始方法所有接口
    参数3:规则:invoke方法,首先调用原始方法(传入原始对象接口,参数)

    1. public class UserServiceJDKProxy {
    2. public static UserService createUserServiceJDKProxy(UserService userService) {
    3. ClassLoader cl = userService.getClass().getClassLoader();
    4. Class[] classes = userService.getClass().getInterfaces();
    5. InvocationHandler ih = new InvocationHandler() {
    6. @Override
    7. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    8. Object ret = method.invoke(userService, args);
    9. System.out.println("测试二");
    10. System.out.println("测试三");
    11. return ret;
    12. }
    13. };
    14. UserService service = (UserService) Proxy.newProxyInstance(cl,classes,ih);
    15. return service;
    16. }
    17. }