springAOP底层原理中的JDK和CGLib动态代理

AOP

1). AOP: AOP Aspect Oriented Programing 面向切面编程
2).AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
3). Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行
期通过代理方式向目标类织入增强代

正常使用类:*.java -> javac -> .class -> java -> 加载该class到虚拟机
动态代理 直接生成了
.class字节码, 加载该class到虚拟机

AOP的好处

为什么说 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码呢?
在这里插入图片描述

为什么spring要采用aop横向抽取机制?
因为传统的纵向继承方式,是采用继承的方式来利用这些重复的代码。这样做会增加类与类的耦合性,程序会显得特别笨重,而且后期也难以维护。
而aop采用的横向抽取机制则避免了这一问题。

AOP底层原理;

AOP的这种横向抽取机制就是采用了代理机制。
spring默认使用jdk动态代理,如果没有实现接口,就使用cglib代理
1)JDK动态代理:只能针对接口实现代理, jdk动态代理在高版本中性能优于CGLib

//目标类和代理类实现的 接口
public interface UserDao {

   public void insert();

    public void delete();

    public void update();

    public void select();
}
//目标类
public class UserDaoTarget implements UserDao {
    public void insert() {
        System.out.println("插入方法");
    }

    public void delete() {
        System.out.println("删除方法");
    }

    public void update() {
        System.out.println("更新方法");
    }

    public void select() {
        System.out.println("查询方法");
    }
}
//代理类
public class ProxyUserDao {
   private UserDao userDao;

    public ProxyUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public UserDao createProxy(){
        //获得类加载器
        ClassLoader classLoader = userDao.getClass().getClassLoader();
        //代理对象需要实现的接口
        Class<?>[] interfaces = userDao.getClass().getInterfaces();
        //通知类
        UserDaoAdvice userDaoAdvice = new UserDaoAdvice();
        UserDao proxy = (UserDao) Proxy.newProxyInstance(classLoader,interfaces,userDaoAdvice);
        return proxy;
    }
}
//通知类
public class UserDaoAdvice implements InvocationHandler {
    UserDao userDao = new UserDaoTarget();

    //调用目标对象中的任意方法都相当于调用该invoke方法。
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("方法被执行,记录日志信息");
        Object obj = method.invoke(userDao,args);

        return obj;
    }
}
//测试类
public class ProxyTest {

    @Test
    public void test() {

        UserDao userdao = new UserDaoTarget();
        //获得代理对象
        UserDao proxy =  new ProxyUserDao(userdao).createProxy();
        //代理对象调用方法
        proxy.delete();
    }
}

2).CGLib动态代理:既可以针对接口实现代理,也可以生成子类充当目标父类的代理

//目标类
public class ProductDao {

    public void select() {
        System.out.println("查询商品");
    }

    public void insert(){
        System.out.println("插入商品");
    }

    public void update(){
        System.out.println("更新商品");
    }

    public void delete(){
        System.out.println("删除商品");
    }

}
//代理类
public class CGLibProxy {
   private ProductDao productDao;
    public CGLibProxy(ProductDao productDao) {
        this.productDao = productDao;
    }
    public ProductDao createproxy(){
        //创建核心类
        Enhancer enhancer = new Enhancer();
        //为其设置父类
        enhancer.setSuperclass(productDao.getClass());
        //设置回调
        enhancer.setCallback(new ProductDaoAdvice());

        //创建代理

        return (ProductDao) enhancer.create();
    }
}
//通知类
public class ProductDaoAdvice implements MethodInterceptor {
    ProductDao productDao = new ProductDao();
    /*
         方法参数说明:Object o 目标对象
                      Method method  方法对象
                      Object[] objects 方法中的参数
                      MethodProxy methodProxy
     */
    public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println("执行了方法,记录了日志信息");
        Object o1 = method.invoke(productDao);
        // CGLib特有的方式 :Object o = methodProxy.invokeSuper(proxy);
        return o1;
    }
}
测试类
public class CGLibTest {
    ProductDao productDao = new ProductDao();
    @Test
    public void test2(){
        ProductDao createproxy = new CGLibProxy(productDao).createproxy();
        createproxy.delete();
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值