JDK代理与CGLib代理区别

JDK动态代理与CGLib动态代理区别:
1、JDK动态代理基于接口实现,所以实现JDK动态代理,必须先定义接口;CGLib动态代理基于被代理类实现;
2、JDK动态代理机制是委托机制,委托hanlder调用原始实现类方法;CGLib则使用继承机制,被代理类和代理类是继承关系,所以代理类对象可以赋值给被代理类类型的变量;如果被代理类有接口,那么代理类对象也可以赋值给该接口类型的变量。

输出JDK动态代理产生的class文件,如下代码:

package com.jd.calculator;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect//将该类声明为切面类
@Component//将该类对象放入IOC容器
public class CalculatorAspect {
	
	//前置增强(又称前置通知):在目标方法开始之前执行
	@Before("execution(public int com.jd.calculator.CalculatorService.*(..))")
	public void before(JoinPoint joinPoint) {
		Object target=joinPoint.getTarget();
		String methodName = joinPoint.getSignature().getName();
		Object[] params = joinPoint.getArgs();
		
		System.out.println(target.getClass().getName()+":The "+methodName+" method begins.");
		System.out.println(target.getClass().getName()+":Parameters of the "+methodName+" method: ["+params[0]+","+params[1]+"]");
	}
}

package com.jd.calculator;

import org.springframework.stereotype.Service;

@Service
public class CalculatorService implements ICalculatorService {

	@Override
	public int mul(int a, int b) {
		int result = a*b;
		return result;
	}
}

package com.jd.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jd.calculator.ICalculatorService;

public class Test {

	public static void main(String[] args) {
		System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");//生成使用JDK创建动态代理对象的class文件。注意:该行代码必须放在代理对象产生之前
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
		
		ICalculatorService calculatorService =applicationContext.getBean(ICalculatorService.class);
		Class<?> clazz = calculatorService.getClass();
		System.out.println(clazz.getName());
		
		applicationContext.close();
	}
}

<?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.calculator"/>
	<aop:aspectj-autoproxy proxy-target-class="false"/>
</beans>

输出CGLib动态代理产生的class文件,如下代码:

package com.jd.test;

import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jd.calculator.ICalculatorService;

public class Test {

	public static void main(String[] args) {
		System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");//生成使用CGLib创建动态代理对象的class文件。注意:该行代码必须放在代理对象产生之前
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
		
		ICalculatorService calculatorService =applicationContext.getBean(ICalculatorService.class);
		
		Class<?> clazz = calculatorService.getClass();
		System.out.println(clazz.getName());

		applicationContext.close();
	}
}

<?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.calculator"/>
	<!-- 使用CGLib生成代理对象 -->
	<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

JDK代理: 代理类和目标类没有继承关系,代理类实现了目标类所实现的接口。
CGLib代理: 代理类继承自目标类。

代理类和目标类是平行关系,代理类和目标类是父子关系。所以当是JDK代理时

IUserInfoService userInfoService = applicationContext.getBean(IUserInfoService.class);

可以获取到代理类对象

IUserInfoService userInfoService = applicationContext.getBean(UserInfoService.class);

这样则不行。
反之,如果是CGLib代理,

IUserInfoService userInfoService = applicationContext.getBean(UserInfoService.class);

依然可以获取到代理类对象。

上一篇:代理模式


下一篇:jdk动态代理和cglib动态代理的区别