Spring动态代理核心底层原理详解AOP,面向切面编程的实现机制-----Spring框架

package com.powernode.proxy.client;

import com.powernode.proxy.Spring6Config;
import com.powernode.proxy.service.OrderService;
import com.powernode.proxy.service.TimerInvocationHandler;
import com.powernode.proxy.service.impl.OrderServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.lang.reflect.Proxy;

public class Client
{
    public static void main(String[] args)
    {
        //创建目标对象
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spring6Config.class);
        OrderService orderService = context.getBean("orderServiceImpl", OrderServiceImpl.class);
        //创建代理对象
        //类加载器,代理类要实现的接口,调用处理器.var返回对象即代理对象
        //newProxyInstance新建代理对象实例
        //本质上,这newProxyInstance()方法执行,在内存中动态生成了代理类的字节码,new了一个对象出来
        //第一个参数 Classloader loader类加载器(代理类的类加载器必须得和被代理对象的类加载器一样)
        //内存当中生成的字节码也是class文件,要执行也必须加载到内存中,加载类就需要类加载器,JDK要求目标类和代理类的加载器必须一样
        //第二个参数 Class<?> interface代理类要实现的接口
        //代理类和目标类要实现同一个接口或同一些接口,要通知JDK我们实现了什么接口,在内存中生成代理类的时候,需要告知实现了那些接口
        //第三个参数 InvocationHandler handler调用处理器,是一个接口
        //因为具体要增强什么代码,卸载调用处理器接口中写增强代码
        Object o = Proxy.newProxyInstance(orderService.getClass().getClassLoader(), orderService.getClass().getInterfaces(), new TimerInvocationHandler(orderService));
        //调用代理对象的代理方法
        //之所以我们可以向下转型,因为我们实现了相同的接口
        OrderService OS = (OrderService)o;
        //调用代理对象的代理方法,如果是增强的话,目标对象的目标方法需要执行
        OS.generate();
        OS.Modify();
        OS.detail();
    }
}
package com.powernode.proxy.client;

import com.powernode.proxy.Spring6Config;
import com.powernode.proxy.service.OrderService;
import com.powernode.proxy.service.TimerInvocationHandler;
import com.powernode.proxy.service.impl.OrderServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.lang.reflect.Proxy;

public class Client
{
    public static void main(String[] args)
    {
        //创建目标对象
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spring6Config.class);
        OrderService orderService = context.getBean("orderServiceImpl", OrderServiceImpl.class);
        //创建代理对象
        //类加载器,代理类要实现的接口,调用处理器.var返回对象即代理对象
        //newProxyInstance新建代理对象实例
        //本质上,这newProxyInstance()方法执行,在内存中动态生成了代理类的字节码,new了一个对象出来
        //第一个参数 Classloader loader类加载器(代理类的类加载器必须得和被代理对象的类加载器一样)
        //内存当中生成的字节码也是class文件,要执行也必须加载到内存中,加载类就需要类加载器,JDK要求目标类和代理类的加载器必须一样
        //第二个参数 Class<?> interface代理类要实现的接口
        //代理类和目标类要实现同一个接口或同一些接口,要通知JDK我们实现了什么接口,在内存中生成代理类的时候,需要告知实现了那些接口
        //第三个参数 InvocationHandler handler调用处理器,是一个接口
        //因为具体要增强什么代码,卸载调用处理器接口中写增强代码
        Object o = Proxy.newProxyInstance(orderService.getClass().getClassLoader(), orderService.getClass().getInterfaces(), new TimerInvocationHandler(orderService));
        //调用代理对象的代理方法
        //之所以我们可以向下转型,因为我们实现了相同的接口
        OrderService OS = (OrderService)o;
        //调用代理对象的代理方法,如果是增强的话,目标对象的目标方法需要执行
        OS.generate();
        OS.Modify();
        OS.detail();
    }
}
package com.powernode.proxy.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class TimerInvocationHandler implements InvocationHandler
{
    private static final Logger logger = LoggerFactory.getLogger(TimerInvocationHandler.class);
    //目标对象
    private Object obj;
    //专门负责计时的调用处理器对象
    //在这个调用处理器中编写负责计时的增强代码
    //为什么要求必须实现InvocationHandler接口的方法,因为已经在其他引用中被调用了
    //因为JDK底层已经调用了invoke方法
    public TimerInvocationHandler(Object obj)
    {
        //赋值给成员变量
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        //当代理对象调用代理方法的时候启用invoke方法,注册在invocationHandler接口中的invoke方法被调用
        //该invoke方法存在的目的就是为了让我们可以写功能增强代码
        //invoke方法是JDK负责调用的,所以我们可以直接使用里面的形参
        //第一个参数是代理对象的引用,第二个是目标方法的目标方法(要执行的目标方法),第三个参数是目标方法上的实参
        long begin = System.currentTimeMillis();
        //调用目标对象的目标方法,方法四要素,谁调用,传什么值,回传什么参数,哪个方法
        Object value = method.invoke(obj, args);
        //invoke方法要调用目标对象的目标方法
        long end = System.currentTimeMillis();
        long time = end - begin;
        logger.info("耗时" + time);
        return value;
    }
}
package com.powernode.proxy.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class TimerInvocationHandler implements InvocationHandler
{
    private static final Logger logger = LoggerFactory.getLogger(TimerInvocationHandler.class);
    //目标对象
    private Object obj;
    //专门负责计时的调用处理器对象
    //在这个调用处理器中编写负责计时的增强代码
    //为什么要求必须实现InvocationHandler接口的方法,因为已经在其他引用中被调用了
    //因为JDK底层已经调用了invoke方法
    public TimerInvocationHandler(Object obj)
    {
        //赋值给成员变量
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        //当代理对象调用代理方法的时候启用invoke方法,注册在invocationHandler接口中的invoke方法被调用
        //该invoke方法存在的目的就是为了让我们可以写功能增强代码
        //invoke方法是JDK负责调用的,所以我们可以直接使用里面的形参
        //第一个参数是代理对象的引用,第二个是目标方法的目标方法(要执行的目标方法),第三个参数是目标方法上的实参
        long begin = System.currentTimeMillis();
        //调用目标对象的目标方法,方法四要素,谁调用,传什么值,回传什么参数,哪个方法
        Object value = method.invoke(obj, args);
        //invoke方法要调用目标对象的目标方法
        long end = System.currentTimeMillis();
        long time = end - begin;
        logger.info("耗时" + time);
        return value;
    }
}
package com.powernode.proxy.service.impl;

import com.powernode.proxy.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

//缺点一:违背了OCP开闭原则,在运行良好的代码上进行了硬编码修改
//缺点二:代码没有得到复用,相同的代码写了很多遍

@Service
public class OrderServiceImpl implements OrderService
{
    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
    @Override
    public void generate()//目标方法
    {
        //模拟网络延迟,模拟生成延迟
        try {
            Thread.sleep(1234);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("订单已生成");
    }

    @Override
    public void Modify()
    {
        //模拟网络延迟,模拟生成延迟
        try {
            Thread.sleep(456);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("订单已修改");
    }

    @Override
    public void detail()
    {
        //模拟网络延迟,模拟生成延迟
        try {
            Thread.sleep(111);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("订单详情如下");
    }
}
package com.powernode.proxy.service.impl;

import com.powernode.proxy.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

//缺点一:违背了OCP开闭原则,在运行良好的代码上进行了硬编码修改
//缺点二:代码没有得到复用,相同的代码写了很多遍

@Service
public class OrderServiceImpl implements OrderService
{
    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
    @Override
    public void generate()//目标方法
    {
        //模拟网络延迟,模拟生成延迟
        try {
            Thread.sleep(1234);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("订单已生成");
    }

    @Override
    public void Modify()
    {
        //模拟网络延迟,模拟生成延迟
        try {
            Thread.sleep(456);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("订单已修改");
    }

    @Override
    public void detail()
    {
        //模拟网络延迟,模拟生成延迟
        try {
            Thread.sleep(111);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("订单详情如下");
    }
}
package com.powernode.proxy.service;

import org.springframework.stereotype.Service;

@Service
public interface OrderService//订单业务接口,也是代理对象和目标对象的公共接口
{
    //生成订单
    void generate();
    //修改订单信息
    void Modify();
    //查看订单明细
    void detail();
}
package com.powernode.proxy.service;

import org.springframework.stereotype.Service;

@Service
public interface OrderService//订单业务接口,也是代理对象和目标对象的公共接口
{
    //生成订单
    void generate();
    //修改订单信息
    void Modify();
    //查看订单明细
    void detail();
}
动态生成代理类,目的是减少代理类的数量,解决代码复用的问题
在内存中动态生成类的技术包括:JDK动态代理技术(java自带内置的,只能代理接口),
CGLIB(Code Generate Library)动态代理技术(开源框架,底层用继承方式代理(底层ASM字节码处理框架),可以代理类和接口),
Javassist动态代理技术
动态生成代理类,目的是减少代理类的数量,解决代码复用的问题
在内存中动态生成类的技术包括:JDK动态代理技术(java自带内置的,只能代理接口),
CGLIB(Code Generate Library)动态代理技术(开源框架,底层用继承方式代理(底层ASM字节码处理框架),可以代理类和接口),
Javassist动态代理技术
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旧约Alatus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值