一、JDK代理与CGLib代理区别
1、JDK代理:
只能对实现了接口的类生成代理,而不能针对类。
2、CGLib代理:
针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法(继承),因为是继承,所以该类或方法最好不要声明成final, 对于final类或方法,是无法继承的。
3、何时使用JDK代理与CGLib代理?
①目标对象实现了接口,默认采用JDK代理实现AOP,此时可以强制使用CGLib代理实现AOP。
②目标对象没有实现了接口,必须强制使用CGLib代理实现AOP。
4、如何强制使用CGLib代理实现AOP?
①添加CGLib库。
②在Spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
。
二、举例
1、接口:
package com.jd.computer.service;
public interface IComputerService {
int div(int a, int b);
}
2、接口实现类:
package com.jd.computer.service;
import org.springframework.stereotype.Service;
@Service
public class ComputerService implements IComputerService {
public int div(int a, int b) {
return a/b;
}
}
3、:
package com.jd.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
public class MethodAOP {
public void before(JoinPoint jp) {
Object [] args = jp.getArgs();
Signature signature = jp.getSignature();
String name = signature.getName();
System.out.println("The "+name+" method begins.");
System.out.println("The "+name+" method params ["+args[0]+","+args[1]+"].");
}
}
4、String配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="/schema/beans"
xmlns:xsi="http:///2001/XMLSchema-instance"
xmlns:context="/schema/context"
xmlns:p="/schema/p"
xmlns:util="/schema/util"
xmlns:aop="/schema/aop"
xmlns:tx="/schema/tx"
xsi:schemaLocation="/schema/beans /schema/beans/
/schema/context /schema/context/spring-context-4.
/schema/aop /schema/aop/spring-aop-4.
/schema/tx /schema/tx/spring-tx-4.
/schema/util /schema/util/spring-util-4.">
<context:component-scan base-package=""></context:component-scan>
<bean class="" id="ma"></bean>
<aop:config>
<aop:pointcut expression="execution(public int .*(..))" id="pc"/>
<aop:aspect ref="ma">
<aop:before method="before" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
<!-- proxy-target-class默认为false,使用JDK代理,为true时使用CGLib代理 -->
<aop:aspectj-autoproxy proxy-target-class="false"/>
</beans>
5、测试类:
①使用JDK代理,<aop:aspectj-autoproxy proxy-target-class="false"/>
。
package com.jd.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.jd.computer.service.IComputerService;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("");
//JDK代理,getBean()中必须是接口,不能是目标类。
IComputerService computerService = applicationContext.getBean(IComputerService.class);
Class clazz = computerService.getClass();
//JDK代理:代理类和目标类没有继承关系,().getName()得到父类的类名
System.out.println(clazz.getSuperclass().getName());
applicationContext.close();
}
}
输出如下,可以看出此时运用JDK代理,没有继承关系:
②使用CGLib代理,<aop:aspectj-autoproxy proxy-target-class="true"/>
,
package com.jd.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.jd.computer.service.ComputerService;
import com.jd.computer.service.IComputerService;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("");
//CGLib代理,getBean()可以是接口或者目标类
IComputerService computerService = applicationContext.getBean(ComputerService.class);
Class clazz = computerService.getClass();
//CGLib代理:代理类继承自目标类
System.out.println(clazz.getSuperclass().getName());
applicationContext.close();
}
}
输出如下,可以看出运用CGLib代理,有继承关系: