目录
一、环境配置
首先,创建service层方法div,及其代理类MethodAOP:
-
package club.affengkuang.computer.service;
-
-
import org.springframework.stereotype.Service;
-
-
//服务层
-
@Service
-
public
class ComputerService implements IComputerService{
-
-
public int div(int a, int b) {
-
return a/b;
-
}
-
}
-
package club.affengkuang.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 param ["+args[
0]+
","+args[
1]+
"]");
-
}
-
}
application.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"
-
xmlns:p=
"http://www.springframework.org/schema/p"
-
xmlns:tx=
"http://www.springframework.org/schema/tx"
-
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.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">
-
-
<context:component-scan base-package="club.affengkuang">
</context:component-scan>
-
-
<bean id="ma" class="club.affengkuang.aop.MethodAOP">
</bean>
-
-
<aop:config>
-
<!-- 定义一个aop表达式 -->
-
<aop:pointcut expression="execution(public int club.affengkuang.computer.service.ComputerService.*(..))" id="pc"/>
-
<!-- 设置一个切面类 -->
-
<aop:aspect ref="ma">
-
<aop:before method="before" pointcut-ref="pc"/>
-
</aop:aspect>
-
</aop:config>
-
</beans>
二、如何启动两种代理类
在如下测试类中调用div方法,并打印代理类类名,得到的该类名就是默认的JDK代理类:
-
package club.affengkuang.test;
-
-
import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-
import club.affengkuang.computer.service.IComputerService;
-
-
public
class Test {
-
-
public static void main(String[] args) {
-
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext(
"application.xml");
-
IComputerService computerService = applicationContext.getBean(IComputerService.class);
-
System.out.println(computerService.div(
1,
1));
-
System.out.println(computerService.getClass().getName());
-
applicationContext.close();
-
}
-
}
启动CGlib代理类,只需在application.xml文件中aop:config标签头部将proxy-target-class属性赋值为true即可,该属性默认值为false,也就是默认使用JDK代理类,赋值为true后使用的便是CGlib代理类:
-
<aop:config proxy-target-class="true">
-
<!-- 定义一个aop表达式 -->
-
<aop:pointcut expression="execution(public int club.affengkuang.computer.service.ComputerService.*(..))" id="pc"/>
-
<!-- 设置一个切面类 -->
-
<aop:aspect ref="ma">
-
<aop:before method="before" pointcut-ref="pc"/>
-
</aop:aspect>
-
</aop:config>
这时再调用测试类打印代理类类名,得到的便是CGlib代理类类名:
三、JDK代理类与CGlib代理类区别
JDK代理类:代理类和目标类无直接继承关系,代理类实现的是目标类实现的接口
CGlib代理类:直接继承自目标类
1.证明
如下:首先设置成JDK代理类,并在测试类中输出代理类所实现的接口,得到了目标类所实现的IComputerService接口:
-
package club.affengkuang.test;
-
-
import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-
import club.affengkuang.computer.service.IComputerService;
-
-
public
class Test {
-
-
@SuppressWarnings(
"rawtypes")
-
public static void main(String[] args) {
-
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext(
"application.xml");
-
IComputerService computerService = applicationContext.getBean(IComputerService.class);
-
Class clazz = computerService.getClass();
-
for(Class c:clazz.getInterfaces()) {
-
System.out.println(c);
-
}
-
applicationContext.close();
-
}
-
}
再将其设置成CGlib代理类,并在测试类中打印所继承的父类,得到了目标类:
-
package club.affengkuang.test;
-
-
import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-
import club.affengkuang.computer.service.IComputerService;
-
-
public
class Test {
-
-
@SuppressWarnings(
"rawtypes")
-
public static void main(String[] args) {
-
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext(
"application.xml");
-
IComputerService computerService = applicationContext.getBean(IComputerService.class);
-
Class clazz = computerService.getClass();
-
System.out.println(clazz.getSuperclass());
-
applicationContext.close();
-
}
-
}
2.影响
CGlib代理类直接继承自目标类,也就意味着在IOC容器中既可以通过目标类实现的接口获取代理类,也可以通过目标类获取代理类,将第13行getBean方法的参数改为通过目标类获取,同样可以得到代理类:
-
package club.affengkuang.test;
-
-
import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-
import club.affengkuang.computer.service.ComputerService;
-
import club.affengkuang.computer.service.IComputerService;
-
-
public
class Test {
-
-
@SuppressWarnings(
"rawtypes")
-
public static void main(String[] args) {
-
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext(
"application.xml");
-
IComputerService computerService = applicationContext.getBean(ComputerService.class);
-
System.out.println(computerService.getClass().getName());
-
applicationContext.close();
-
}
-
}
而JDK代理类和目标类无直接继承关系,所以只能通过接口获取代理类,将proxy-target-class属性改为false,即使用JDK代理类,再执行上述测试类,则会抛出异常:
转载:https://blog.csdn.net/DangerousMc/article/details/104920729
查看评论