AOP实现原理 CGLib与JDK动态代理

Spring AOP实现原理

 Spring基于代理模式实现功能动态扩展,包含两种形式: 

  1.目标类拥有接口,通过JDK动态代理实现功能扩展。

  2.目标类没有接口,通过CGLib组件实现功能扩展

 

代理模式

 代理模式通过 代理对象 对 原对象的实现功能 进行拓展

 

静态代理

 静态代理实现功能拓展,实现目标方法执行前打印时间这一功能

package com.spring.aop.service;

public interface UserService {
    public void createUser();
}
复制代码
package com.spring.aop.service;

public class UserServiceImpl implements UserService{
    @Override
    public void createUser() {
        System.out.println("执行创建用户业务逻辑");
    }
}
复制代码
复制代码
package com.spring.aop.service;

import java.text.SimpleDateFormat;
import java.util.Date;

public class UserServiceProxy implements UserService{
    //代理类特点:持有委托类的对象
    private UserService userService;

    //在创建代理对象UserServiceProxy时,通过外部传入的参数UserService实现类,为内部委托类赋值
    public UserServiceProxy(UserService userService){
        this.userService = userService;
    }

    @Override
    public void createUser() {
        //功能的拓展,在执行目标方法之前打印时间
        System.out.println("=====" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()) + "=====");
        userService.createUser();
    }
}
复制代码
复制代码
package com.spring.aop;

import com.spring.aop.service.UserService;
import com.spring.aop.service.UserServiceImpl;
import com.spring.aop.service.UserServiceProxy;

public class Application {
    public static void main(String[] args) {
        UserService userService = new UserServiceProxy(new UserServiceImpl());
        userService.createUser();
    }
}
复制代码

 

 代理模式可以嵌套使用

 在上述代理模式上增加一个代理类UserServiceProxy1实现后置通知功能

复制代码
package com.spring.aop.service;

public class UserServiceProxy1 implements UserService{
    private UserService userService;
    public UserServiceProxy1(UserService userService){
        this.userService = userService;
    }

    @Override
    public void createUser() {
        userService.createUser();
        System.out.println("========后置通知==========");
    }
}
复制代码
复制代码
package com.spring.aop;

import com.spring.aop.service.UserService;
import com.spring.aop.service.UserServiceImpl;
import com.spring.aop.service.UserServiceProxy;
import com.spring.aop.service.UserServiceProxy1;

public class Application {
    public static void main(String[] args) {
        UserService userService = new UserServiceProxy1(new UserServiceProxy(new UserServiceImpl()));
        userService.createUser();
    }
}
复制代码

 

 静态代理中,每进行一次功能拓展都需要手动创建一个代理类,随着大型项目的功能不断完善,每一个业务实现类都要至少拥有一个代理类,当业务实现类数量极高时,是否还需要给每一个实现类增加对应的代理类?

动态代理

 反射机制可以根据要实现的接口结构,自动生成相应的代理类,完成目标方法的扩展工作,这个过程中代理类是通过反射在运行时自动生成的。静态代理需要手写代理类,动态代理根据接口结构在运行时自动地动态生成

 基于JDK动态代理完成对UserServiceImpl实现类的功能扩展

 

package com.spring.aop.service;

public interface UserService {
    public void createUser();
}
复制代码
package com.spring.aop.service;

public class UserServiceImpl implements UserService{
    @Override
    public void createUser() {
        System.out.println("执行创建用户业务逻辑");
    }
}
复制代码
复制代码
package com.spring.aop.service;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * InvocationHandler是JDK提供的反射类,用于在JDK动态代理中对目标方法进行增强
 * InvocationHandler实现类与切面类的环绕通知相似
 */
public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;//目标对象
    private ProxyInvocationHandler(Object target){
        this.target = target;
    }
    /**
     * 在invoke()方法对目标进行增强
     * @param proxy 代理类对象
     * @param method 目标方法对象
     * @param args 目标方法实参
     * @return 目标方法运行后返回值
     * @throws Throwable 目标方法抛出的异常
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("=====" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()) + "=====");
        Object ret = method.invoke(target, args);//调用目标方法,对应环绕通知中ProceedingJoinPoint.proceed()

        return ret;
    }

    public static void main(String[] args) {
        //动态代理必须实现接口才可以运行
        UserService userService = new UserServiceImpl();
        ProxyInvocationHandler invocationHandler = new ProxyInvocationHandler(userService);
        //动态创建代理类
        //Proxy.newProxyInstance方法用于基于接口创建指定代理类
        // 三个参数: 类加载器,userService要实现的接口对象,invocationHandler对象
        UserService userServiceProxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),
                invocationHandler);
        userServiceProxy.createUser();
    }
}
复制代码

 

 CGLib 运行时字节码增强技术

 Spring AOP拓展无接口类使用CGLib,当目标类无实现接口,AOP会运行时生成 目标继承类字节码 的方式进行行为拓展。CGLib的实现原理是,在原始目标类的基础上进行继承,然后重写每一个方法进行增强

 当UserService实现了某个接口时,Spring AOP会优先选择动态代理实现功能增强

 

 

 

posted @   南风知君  阅读(167)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示