Spring框架中的JDK与CGlib动态代理

本文探讨了Spring框架中JDK和CGlib动态代理的区别。当proxy-target-class设为true时,CGlib基于目标类创建代理,而JDK则基于接口。CGlib代理产生的是目标类的子类,JDK代理则是目标类实现接口的实现类。在事务处理中,两种代理方式各有应用场景。推荐阅读相关面试真题系列文章。
摘要由CSDN通过智能技术生成

CGlib:可以是接口也可以是类

这里讨论的是test类中(是用接口还是目标类)

IMathService mathService = applicationContext.getBean(MathService.class);
test类中源码:

package com.jd.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jd.math.IMathService;
import com.jd.math.MathService;

public class Test {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        //true的时候是根据目标类来创建,false是根据接口来创建的,只能通过接口。
        IMathService mathService = applicationContext.getBean(MathService.class);
        System.out.println(mathService.getClass());
        applicationContext.close();
    }
}复制代码

xml源码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

  <context:component-scan base-package="com.jd"></context:component-scan>
  <!-- true基于目标类来创建  false是基于接口 -->
  <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>复制代码

引用jar包:

这里在xml中;proxy-target-class="true" true的时候是根据目标类来创建,false是根据接口来创建的,只能通过接口

运行结果:

文件结构:

CGlib动态代理所产生的代理类是目标子类
JDK动态代理产生的代理类与目标的继承关系,其代理类是目标类所实现的接口的实现类

CGlib测试:xml中改为true

test类源码:

package com.jd.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jd.math.IMathService;
import com.jd.math.MathService;

public class Test {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        //true的时候是根据目标类来创建,false是根据接口来创建的,只能通过接口。jdk只能用接口
        //CGlib3.2开始自身支持CGlib
        IMathService mathService = applicationContext.getBean(MathService.class);
        //CGlib动态代理所产生的代理类是目标子类
        //JDK动态代理产生的代理类与目标的继承关系,其代理类是目标类所实现的接口的实现类
        System.out.println(mathService.getClass().getSuperclass());
        Class clazz = mathService.getClass();
        Class [] array = clazz.getInterfaces();
        for(Class c:array) {
            System.out.println(c.getName());
        }
        applicationContext.close();
    }
}复制代码

运行结果:
class com.jd.math.MathService
org.springframework.aop.SpringProxy

org.springframework.aop.framework.Advised
org.springframework.cglib.proxy.Factory

JDK测试:xml中改为false

test类中

这里为IMathService。

运行结果:

class java.lang.reflect.Proxy
com.jd.math.IMathService

org.springframework.aop.SpringProxy

org.springframework.aop.framework.Advised

org.springframework.core.DecoratingProxy

事务中这两种讨论:CGlib

test源码:

package com.jd.test;

import java.util.HashMap;
import java.util.Map;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jd.car.CarService;
import com.jd.car.ICarService;
import com.jd.coupon.service.CouponService;
import com.jd.coupon.service.ICouponService;

public class Test {

    /*public static void main(String[] args) {
        ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("application.xml");

        //立即购买
        ICouponService couponService = application.getBean(ICouponService.class);
        System.out.println(couponService.getClass().getName());

    //  String userId = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
    //  String bookId = "8" ;
        //String bookId = "445" ;
        //库存有10本 他一次买了5本
    //  int count=7;

        if(couponService.insert(userId, bookId, count)) {

            System.out.println("OK");
        }

        //购物车购买
        ICarService carService = application.getBean(ICarService.class);
        String userId = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
        Map<String,Integer> commodities = new HashMap<String,Integer>();
        //买两本书
        commodities.put("a2f39533-659f-42ca-af91-c688a83f6e49",1);
        commodities.put("4c37672a-653c-4cc8-9ab5-ee0c614c7425",1);
        carService.batch(userId, commodities);
        application.close();
    }*/

    public static void main(String[] args) {
        //一个类中的方法被@Transctional注解修饰,则Spring自动为该类创建代理类及代理对象   
        ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("application.xml");
        ICarService carService = application.getBean(CarService.class);
        System.out.println(carService.getClass().getName());
        application.close();
    }
}复制代码

test类中:ICarService carService = application.getBean(CarService.class);

这里为CarService.class

配置xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

<!-- 创建IOC容器的时候就会扫描com.jd包下所有的类 -->
<context:component-scan base-package="com.jd"></context:component-scan>

<bean id="dataSource"  class="com.zaxxer.hikari.HikariDataSource" destroy-method="close" p:password="123456" p:username="root">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/test"></property>
</bean>

<!-- 对JDBC进行配置    因为是引用类型所以用p:dataSource-ref=""-->
<bean class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource"></bean>

<!-- 配置数据源事务管理器-->
<bean id="transactionManeger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

</beans>复制代码

这里:<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

为true时

true的时候是根据目标类来创建,false是根据接口来创建的,只能通过接口

运行结果:

com.jd.car.CarService

EnhancerBySpringCGLIB

40b982ec

JDK代理:

test类中改为:

ICarService carService = application.getBean(ICarService.class);
xml中改为:

<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>

运行结果:
com.sun.proxy.$Proxy11
得证!

推荐阅读:

【备战春招系列】关于kafka,BAT大厂都喜欢怎么问?

【备战春招系列】ZooKeeper灵魂28问,教你如何搞定面试官!

【备战春招系列】最新Linux 面试真题45道

【备战春招系列】历年来关于MySQL高频面试真题的梳理

【备战春招系列】springBoot灵魂22问!

【备战春招系列】50道微服务面试真题详解

【备战春招系列】27道MyBatis面试真题详解

大厂resdis灵魂40问,教你如何搞定面试官

更多技术文章和面试真题可以关注微信公众号:Java程序员聚集地。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值