JDK 动态代理是通过 JDK 中的 java.lang.reflect.Proxy 类实现的。下面通过具体的案例演示 JDK 动态代理的使用。
1. 创建项目
在 MyEclipse 中创建一个名称为 springDemo03 的 Web 项目,将 Spring 支持和依赖的 JAR 包复制到 Web 项目的 WEB-INF/lib 目录中,并发布到类路径下。
2. 创建接口 CustomerDao
在项目的 src 目录下创建一个名为 com.mengma.dao 的包,在该包下创建一个 CustomerDao 接口,编辑后如下所示。
package com.mengma.dao;
public interface CustomerDao {
public void add(); // 添加
public void update(); // 修改
public void delete(); // 删除
public void find(); // 查询
}
3. 创建实现类 CustomerDaoImpl
在 com.mengma.dao 包下创建 CustomerDao 接口的实现类 CustomerDaoImpl,并实现该接口中的所有方法,如下所示。
package com.mengma.dao;
public class CustomerDaoImpl implements CustomerDao {
@Override
public void add() {
System.out.println("添加客户...");
}
@Override
public void update() {
System.out.println("修改客户...");
}
@Override
public void delete() {
System.out.println("删除客户...");
}
@Override
public void find() {
System.out.println("修改客户...");
}
}
4. 创建切面类 MyAspect
在 src 目录下,创建一个名为 com.mengma.jdk 的包,在该包下创建一个切面类 MyAspect,编辑后如下所示。
package com.mengma.jdk;
public class MyAspect {
public void myBefore() {
System.out.println("方法执行之前");
}
public void myAfter() {
System.out.println("方法执行之后");
}
}
上述代码中,在切面中定义了两个增强的方法,分别为 myBefore() 方法和 myAfter() 方法,用于对目标类(CustomerDaoImpl)进行增强。
5. 创建代理类 MyBeanFactory
在 com.mengma.jdk 包下创建一个名为 MyBeanFactory 的类,在该类中使用 java.lang.reflect.Proxy 实现 JDK 动态代理,如下所示。
package com.mengma.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.mengma.dao.CustomerDao;
import com.mengma.dao.CustomerDaoImpl;
public class MyBeanFactory {
public static CustomerDao getBean() {
// 准备目标类
final CustomerDao customerDao = new CustomerDaoImpl();
// 创建切面类实例
final MyAspect myAspect = new MyAspect();
// 使用代理类,进行增强
return (CustomerDao) Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(),
new Class[] { CustomerDao.class }, new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
myAspect.myBefore(); // 前增强
Object obj = method.invoke(customerDao, args);
myAspect.myAfter(); // 后增强
return obj;
}
});
}
}
上述代码中,定义了一个静态的 getBean() 方法,这里模拟 Spring 框架的 IoC 思想,通过调用 getBean() 方法创建实例,第 14 行代码创建了 customerDao 实例。
第 16 行代码创建的切面类实例用于调用切面类中相应的方法;第 18~26 行就是使用代理类对创建的实例 customerDao 中的方法进行增强的代码,其中 Proxy 的 newProxyInstance() 方法的第一个参数是当前类的类加载器,第二参数是所创建实例的实现类的接口,第三个参数就是需要增强的方法。
在目标类方法执行的前后,分别执行切面类中的 myBefore() 方法和 myAfter() 方法。
6. 创建测试类 JDKProxyTest
在 com.mengma.jdk 包下创建一个名为 JDKProxyTest 的测试类,如下所示。
package com.mengma.jdk;
import org.junit.Test;
import com.mengma.dao.CustomerDao;
public class JDKProxyTest {
@Test
public void test() {
// 从工厂获得指定的内容(相当于spring获得,但此内容时代理对象)
CustomerDao customerDao = MyBeanFactory.getBean();
// 执行方法
customerDao.add();
customerDao.update();
customerDao.delete();
customerDao.find();
}
}
上述代码中,在调用 getBean() 方法时,获取的是 CustomerDao 类的代理对象,然后调用了该对象中的方法。
7. 运行项目并查看结果
使用 JUnit 测试运行 test() 方法,运行成功后,控制台的输出结果
吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring JDK动态代理的更多相关文章
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:继承的应用
class Array{ // 表示数组 private int temp[] ; // 整型数组 private int foot ; // 定义添加位置 public Array(int len) ...
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:匿名内部类
interface A{ public void printInfo() ; // } class B implements A{ // 实现接口 public void printInfo(){ S ...
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:包装类
public class WrapperDemo01{ public static void main(String args[]){ int x = 30 ; // 基本数据类型 Integer i ...
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:Object类
class Demo{ // 定义Demo类,实际上就是继承了Object类 }; public class ObjectDemo01{ public static void main(String ...
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:宠物商店实例分析
interface Pet{ // 定义宠物接口 public String getName() ; public String getColor() ; public int getAge() ; ...
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:抽象类与接口的应用
abstract class A{ // 定义抽象类A public abstract void print() ; // 定义抽象方法print() }; class B extends A { / ...
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:instanceof关键字
class A{ // 定义类A public void fun1(){ // 定义fun1()方法 System.out.println("A --> public void fun ...
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:对象的多态性
class A{ // 定义类A public void fun1(){ // 定义fun1()方法 System.out.println("A --> public void fun ...
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:接口的基本实现
interface A{ // 定义接口A public static final String AUTHOR = "李兴华" ; // 全局常量 public abstract ...
-
吴裕雄--天生自然JAVA面向对象高级编程学习笔记:final关键字
final class A{ // 使用final定义类,不能有子类 }; class B extends A{ // 错误,不能被继承 }; class A{ public final void p ...
随机推荐
-
SQL中使用or影响性能的解决办法
近期做了一个存储过程,执行时发现非常的慢,竟然需要6.7秒! 经排查,发现时间主要都耗在了其中一段查询语句上.这个语句用于查出结构相同的两个表中,其中两个字段的任一个字段数据相同的记录. 例如,A表的 ...
-
[JS]笔记12之事件机制--事件冒泡和捕获--事件监听--阻止事件传播
-->事件冒泡和捕获-->事件监听-->阻止事件传播 一.事件冒泡和捕获 1.概念:当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,点击子元素时,父元素的oncl ...
-
java多线程学习
在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口. 一.扩展java.lang.Thread类 package com.multithread.lea ...
-
validate 的插件用法
1.不推荐使用控件方式验证的方式(因为他严重的影响的html代码,也不便于语义化) <input type="text" class="required" ...
-
AOJ 2170 Marked Ancestor (基础并查集)
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=45522 给定一棵树的n个节点,每个节点标号在1到n之间,1是树的根节点,有如 ...
-
车牌识别LPR(五)-- 一种车牌定位法
该方法是某个文章中看到的,有点忘了是那一篇了,看的太多也太久了. Step1.把采集到的RGB图像转换为HSI图像. HSI模型能反映人对色彩的感知和鉴别能力,非常适合基于色彩的图像的相似比较,故采用 ...
-
简单dp-poj-2231-Moo Volume
题目链接: http://poj.org/problem?id=2231 题目大意: 给n个位置,求所有位置到其他n-1个位置的距离总和. 解题思路: 简单dp. o(n^2)的时间复杂度会超.先对这 ...
-
PHP 生成.csv 文件并下载到浏览器
近期做了一个项目须要把订单的信息显示出来.而且可以把相关信息放到一个.csv 文件里,下载到浏览器.首先我要说明的是.csv 文件,PHP 有专门的函数去解析该类型的文件,相关函数大家可以去官网查看. ...
-
Mysql优化--慢查询日志
Mysql 系列文章主页 =============== 默认没有开启慢查询日志功能.如果不是调优需要的话,一般不建议开启. 查看是否开启慢查询日志: SHOW VARIABLES LIKE '%sl ...
-
关于阿里云Centos7 Mailx发送邮件失败的处理
开始通过配置系统自带的mail 发送邮件 在其中一台服务器怎么都不行 /etc/mail.rc配置: set from="邮箱名" set smtp="smtp.163. ...