jdk的动态代理大家应该都听说过,条件是必须要有接口;cglib不要求接口,那么它是怎么实现切面的呢?很简单,通过继承,它动态的创建出一个目标类的子类,复写父类的方法,由此实现对方法的增强。看例子:

  spring-core.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd ">
<context:annotation-config />
<context:component-scan base-package="com.wulinfeng.test.testpilling" />
<bean class="com.wulinfeng.test.testpilling.util.PropertiesConfigUtil">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath:global.properties</value>
</list>
</property>
<property name="fileEncoding">
<value>UTF-8</value>
</property>
</bean> <bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod"
value="com.wulinfeng.test.testpilling.service.TestPillingService.init" />
</bean> <bean id="advice" class="com.wulinfeng.test.testpilling.util.TimeCostUtil" /> <aop:config>
<aop:pointcut
expression="execution(* com.wulinfeng.*.testpilling.service..*Service.*(..))"
id="pointCut" />
<aop:advisor advice-ref="advice" pointcut-ref="pointCut" />
</aop:config>
</beans>

  通知类:

package com.wulinfeng.test.testpilling.util;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; /**
* 统计接口时延
*
* @author wulinfeng
* @version C10 2018年11月19日
* @since SDP V300R003C10
*/
public class TimeCostUtil implements MethodInterceptor
{
private static Logger LOGGER = LogManager.getLogger(TimeCostUtil.class); @Override
public Object invoke(MethodInvocation invocation)
throws Throwable
{
// 获取服务开始时间
long beginTime = System.currentTimeMillis(); // 获取类名和方法名
String srcClassName = "";
String methodName = "";
if (invocation != null)
{
String className = invocation.getClass() != null ? invocation.getClass().getName() : "";
LOGGER.debug("The proxy class name is : " + className);
if (invocation.getMethod() != null)
{
methodName = invocation.getMethod().getName();
}
if (invocation.getThis() != null && invocation.getThis().getClass() != null)
{
srcClassName = invocation.getThis().getClass().getName(); }
} // 调用原来的方法
Object result = invocation.proceed(); // 打印耗时
LOGGER.debug(srcClassName + "." + methodName + " cost time: " + (System.currentTimeMillis() - beginTime)); return result;
} }

  目标类:

package com.wulinfeng.test.testpilling.service;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.concurrent.Executors; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service; /**
* 监听文件修改,打印到日志里
*
* @author wulinfeng
* @version C10 2018年11月20日
* @since SDP V300R003C10
*/
@Service
public class FileListenServiceImpl implements FileListenService
{
private static Logger LOGGER = LogManager.getLogger(FileListenServiceImpl.class); @Override
public void updateOnListen(String filePath)
throws IOException
{
LOGGER.debug("The file path is : " + filePath); // 监听文件所在路径
Path path = Paths.get(filePath);
final WatchService ws = FileSystems.getDefault().newWatchService();
path.register(ws,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_CREATE);
Executors.newCachedThreadPool().execute(new Runnable()
{ @Override
public void run()
{
while (true)
{
try
{
WatchKey key = ws.take();
for (WatchEvent<?> event : key.pollEvents())
{
System.out.println(event.kind().toString());
if (event.kind().equals(StandardWatchEventKinds.ENTRY_CREATE))
{
Path createdPath = (Path)event.context();
createdPath = path.resolve(createdPath);
long size = Files.size(createdPath);
LOGGER.debug("create file : " + createdPath + "==>" + size);
}
else if (event.kind().equals(StandardWatchEventKinds.ENTRY_MODIFY))
{
Path createdPath = (Path)event.context();
createdPath = path.resolve(createdPath);
long size = Files.size(createdPath);
LOGGER.debug("update file : " + createdPath + "==>" + size);
}
else if (event.kind().equals(StandardWatchEventKinds.ENTRY_DELETE))
{
Path createdPath = (Path)event.context();
createdPath = path.resolve(createdPath);
LOGGER.debug("delete file : " + createdPath);
}
}
key.reset();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
});
} }

  另一个TestPillingService没有实现接口,不贴了,看下单测:

package com.wulinfeng.test.testpilling;

import java.io.IOException;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.wulinfeng.test.testpilling.service.FileListenService;
import com.wulinfeng.test.testpilling.service.TestPillingService;
import com.wulinfeng.test.testpilling.util.PropertiesConfigUtil; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-core.xml"})
public class TimeCostUtilTest
{
@Autowired
TestPillingService tps; @Autowired
FileListenService fls;
@Test
public void timeCostTest()
throws IOException
{
String CLASS_PATH = TestPillingService.class.getResource("/").getPath().startsWith("/")
? TestPillingService.class.getResource("/").getPath().substring(1)
: TestPillingService.class.getResource("/").getPath();
String filePath = CLASS_PATH + PropertiesConfigUtil.getProperty("filepath", "methods");
fls.updateOnListen(filePath);
tps.editMethodContent("test", "hello world!");
} }

  运行结果:

log4j:WARN No appenders could be found for logger (org.springframework.test.context.junit4.SpringJUnit4ClassRunner).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
ERROR StatusLogger Unable to locate appender "httpClient-log" for logger config "org.asynchttpclient"
[2018-11-20 12:53:18] DEBUG TestPillingService:71 - Enter TestPillingService.init, filePath : methods, loginPath : login
[2018-11-20 12:53:18] DEBUG TimeCostUtil:32 - The proxy class name is : org.springframework.aop.framework.ReflectiveMethodInvocation
[2018-11-20 12:53:18] DEBUG FileListenServiceImpl:34 - The file path is : E:/workspace/Wireless-Router/test-pilling/target/test-classes/methods
[2018-11-20 12:53:18] DEBUG TimeCostUtil:48 - com.wulinfeng.test.testpilling.service.FileListenServiceImpl.updateOnListen cost time: 6
[2018-11-20 12:53:18] DEBUG TimeCostUtil:32 - The proxy class name is : org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation
[2018-11-20 12:53:18] DEBUG TimeCostUtil:48 - com.wulinfeng.test.testpilling.service.TestPillingService.editMethodContent cost time: 43
ENTRY_CREATE
[2018-11-20 12:53:18] DEBUG FileListenServiceImpl:62 - create file : E:\workspace\Wireless-Router\test-pilling\target\test-classes\methods\test==>0
ENTRY_MODIFY
[2018-11-20 12:53:18] DEBUG FileListenServiceImpl:69 - update file : E:\workspace\Wireless-Router\test-pilling\target\test-classes\methods\test==>14

  我们看到jdk动态代理的实际实现类是ReflectiveMethodInvocation,它最终实现了MethodInterceptor接口的invoke方法和MethodInvocation接口的getMethod方法;而cglib动态代理实际实现类为CglibAopProxy的内部类CglibMethodInvocation(它继承自ReflectiveMethodInvocation,复写了invokeJoinpoint方法)。他们俩执行目标类的实际方法时都是通过ReflectiveMethodInvocation的proceed来进行的。

  如果我们把<aop:config>改成这样:

<aop:config proxy-target-class="true">

  测试结果:

log4j:WARN No appenders could be found for logger (org.springframework.test.context.junit4.SpringJUnit4ClassRunner).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
ERROR StatusLogger Unable to locate appender "httpClient-log" for logger config "org.asynchttpclient"
[2018-11-20 13:05:12] DEBUG TestPillingService:71 - Enter TestPillingService.init, filePath : methods, loginPath : login
[2018-11-20 13:05:13] DEBUG TimeCostUtil:32 - The proxy class name is : org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation
[2018-11-20 13:05:13] DEBUG FileListenServiceImpl:34 - The file path is : E:/workspace/Wireless-Router/test-pilling/target/test-classes/methods
[2018-11-20 13:05:13] DEBUG TimeCostUtil:48 - com.wulinfeng.test.testpilling.service.FileListenServiceImpl.updateOnListen cost time: 50
[2018-11-20 13:05:13] DEBUG TimeCostUtil:32 - The proxy class name is : org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation
[2018-11-20 13:05:13] DEBUG TimeCostUtil:48 - com.wulinfeng.test.testpilling.service.TestPillingService.editMethodContent cost time: 42
ENTRY_DELETE
[2018-11-20 13:05:13] DEBUG FileListenServiceImpl:75 - delete file : E:\workspace\Wireless-Router\test-pilling\target\test-classes\methods\test
ENTRY_CREATE
[2018-11-20 13:05:13] DEBUG FileListenServiceImpl:62 - create file : E:\workspace\Wireless-Router\test-pilling\target\test-classes\methods\test==>0

spring切面配置,代理用jdk和cglib的区别的更多相关文章

  1. Spring的两种动态代理:Jdk和Cglib 的区别和实现

    这是有意义的一天!自己研究一路畅通的感觉真爽 原理是参考大神的,代码手敲 一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处 ...

  2. 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)

    Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC   目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...

  3. [转]java动态代理(JDK和cglib)

    转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...

  4. Spring学习总结(二)——静态代理、JDK与CGLIB动态代理、AOP+IoC

    一.为什么需要代理模式 假设需实现一个计算的类Math.完成加.减.乘.除功能,如下所示: package com.zhangguo.Spring041.aop01; public class Mat ...

  5. Spring的两种代理JDK和CGLIB的区别浅谈

    一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...

  6. Spring学习(四)—— java动态代理(JDK和cglib)

    JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他 的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托 ...

  7. java动态代理(JDK和cglib)(转载)

    原文地址:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html 高亮部分是我的理解. JAVA的动态代理 代理模式 代理模式是常用的j ...

  8. java的静态代理和动态代理(jdk、cglib)

    一.代理模式 代理的概念来自于设计模式中的代理模式,先了解一下代理模式 1.结构图 2.参与者 Subject:接口,定义代理类和实际类的共用接口 RealSubject:实际类,实现Subject这 ...

  9. 动态代理jdk和cglib的区别

    学习来源贴:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类, ...

随机推荐

  1. ATCODER ABC 099

    ATCODER ABC 099 记录一下自己第一场AK的比赛吧...虽然还是被各种踩... 只能说ABC确实是比较容易. A 题目大意 给你一个数(1~1999),让你判断它是不是大于999. Sol ...

  2. All Classic Bluetooth profile for iPhone

    iPhone BC profiles Profile Decription HFP1.6 1.通知客户端有电话拨入:2.免提功能:3.音频的输入输出机制. PBAP 1.下载通讯录:2.查找通讯录:3 ...

  3. spark数据监控实战

    版权申明:转载请注明出处.文章来源:http://bigdataer.net/?p=248 排版乱?请移步原文获得更好的阅读体验   1.概述 数据准确性,稳定性,时效性是数据开发中需要重点关注的,一 ...

  4. Java中的条件运算符

    条件运算符( ? : )也称为 “三元运算符”. 语法形式:布尔表达式 ? 表达式1 :表达式2 运算过程:如果布尔表达式的值为 true ,则返回 表达式1 的值,否则返回 表达式2 的值 例如: ...

  5. VIM操作基础命令

    VIM操作基础命令 1 文件操作 1.1 打开文件 VIM 使用 –o 或 –O 选项打开多个文件,其中 –o 表示垂直并排,例如 vim -o lesson4 lesson5 lesson6.大O表 ...

  6. PHP的可变变量名

    有时候可变的变量名会给编程带来很大的方便.也就是说变量名可以被动态的命名和使用.通常变量通过下面这样的语句来命名 : 1 2 3 <!--?php $a = 'hello'; ?--> 可 ...

  7. codeforces 816B.Karen and Coffee 解题报告

    题目链接:http://codeforces.com/contest/816/problem/B 题目意思:给出 n 个recipes,第 i 个(1<= i <=n)recipes 表明 ...

  8. 关于绑定的C#代码+转换器

    BindingOperations.SetBinding(                exp, Expander.IsExpandedProperty,                new Bi ...

  9. Ajax的跨域问题(包括解决方案)?

    原因:js的同源策略限制,不同源会造成跨域 哪些情况会造成跨域? 子域名不同(WWW) 2.主域名不同(baidu.com) 3.端口号不同 4.IP地址和网址不同 解决方案: 使用jsonp技术,但 ...

  10. mybatis 批量修改接口的几种实现方式

    -----------------我也是有上线的--------------我也是有上线的------------我也是有上线的---------------我也是有上线的-------------- ...