讲了JDK里使用Proxy动态代理的机制,详细过程。

切面类TransactionHandler需要实现InvocationHaandler接口,实现它的invoke方法。

项目目录:

User类代码:

package com.oracle.model;

public class User {

    private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

UserDAO代码:

package com.oracle.dao;

import com.oracle.model.User;

public interface UserDAO {

    void addUser(User u);
void deleteUser(User u); }

UserService代码:

package com.oracle.service.impl;

import com.oracle.dao.UserDAO;
import com.oracle.model.User;
import com.oracle.service.UserService; public class UserServiceImpl implements UserService{ //组合UserDAO
private UserDAO userDAO; //调用的都是UserDAO的方法
public UserServiceImpl(UserDAO userDAO) {
super();
this.userDAO = userDAO;
} @Override
public void addUser(User u) {
this.userDAO.addUser(u); } @Override
public void deleteUser(User u) {
this.userDAO.deleteUser(u); } }

UserServiceImpl代码:

package com.oracle.service.impl;

import com.oracle.dao.UserDAO;
import com.oracle.model.User;
import com.oracle.service.UserService; public class UserServiceImpl implements UserService{ private UserDAO userDAO; public UserServiceImpl(UserDAO userDAO) {
super();
this.userDAO = userDAO;
} @Override
public void addUser(User u) {
this.userDAO.addUser(u); } @Override
public void deleteUser(User u) {
this.userDAO.deleteUser(u); } }

UserDAOImpl代码

package com.oracle.dao.impl;

import com.oracle.dao.UserDAO;
import com.oracle.model.User; public class UserDAOImpl implements UserDAO{ @Override
public void addUser(User u) {
System.out.println("a user added !"); } @Override
public void deleteUser(User u) {
System.out.println("a user deleted !"); } }

UserAction代码:

package com.oracle.action;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import com.oracle.dao.UserDAO;
import com.oracle.dao.impl.UserDAOImpl;
import com.oracle.model.User;
import com.oracle.service.UserService;
import com.oracle.service.impl.UserServiceImpl; public class UserAction { public static void main(String[] args) { //被代理对象
UserDAO userDAO = new UserDAOImpl(); //InvocationHandler
TransactionHandler handler = new TransactionHandler(userDAO); /**
* 返回代理对象:$Proxy0
* Proxy.newProxyInstance三个参数:
* 1,要用哪个ClassLoader来产生代理对象。
* 它和被代理对象使用同一个ClassLoader,因为产生的代理对象里包含了一个被代理对象。
* 2,产生的被代理对象实现了哪些个接口:接口里有哪些方法,生成的代理就有哪些方法
* new Class[]{UserDAO.Class}多个接口时,或userDAO.getClass().getInterfaces()
* 3,当产生代理之后,当调用代理里面方法的时候,用哪一个Handler进行处理
*/
UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(
userDAO.getClass().getClassLoader(),
userDAO.getClass().getInterfaces(),
handler); /**
* 代理对象的方法是怎么产生的?
* 我们的代理对象userDAOproxy里的方法有:
* 1,addUser(User u)
* 2,deleteUser(User u)
* 当代理对象里每一个方法被调用的时候,都会把它自身及参数、代理对象、传给InvocationHandler,
* 也就是我们的TransactionHandler,调用他的invoke方法
*/ /**
* 内部机制:
* Class $Proxy0 implements UserDAO{
* addUser(User u){
* Method m = UserDAO.getClass.getMethod
* handler.invoke(this,m,u);
* }
*
* }
*/ //产生的是不是UserDAO?再看他有哪些方法
//产生的类:$Proxy0 是实现了UserDAO接口了
/*System.out.println(userDAOProxy.getClass().getName());
System.out.println(userDAOProxy instanceof UserDAO);
Method[] methods = userDAOProxy.getClass().getMethods();
for(Method m: methods){
System.out.println(m.getName());
} */ UserService userService = new UserServiceImpl(userDAOProxy);
User u = new User();
u.setAge(20);
u.setName("王彦");
userService.addUser(u);
userService.deleteUser(u); }
}

TransactionHandler代码:

package com.oracle.action;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class TransactionHandler implements InvocationHandler{ private Object target; public TransactionHandler(Object target) {
super();
this.target = target;
} public Object getTarget() {
return target;
} public void setTarget(Object target) {
this.target = target;
} //处理业务逻辑可以传进去Method,进行名字判断,不同的方法做不同的逻辑处理
public void beforeMethod(Method m){
//if(m.getName().equals(anObject))....做不同处理
System.out.println(m.getName()+" beginning...");
}
public void afterMethod(Method m){
System.out.println(m.getName()+" ending...");
} /**
* 三个参数:1,代理对象 2,被调用方法,3,被调用方法的参数
* 代理的哪个方法被掉用,就把代理对象、方法及参数传过来,
* 首先加自己的业务逻辑,再调用被代理对象的方法
*/ @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable { beforeMethod(method);
//调用被代理对象
Object obj = method.invoke(this.target,args);
afterMethod(method);
return obj;
} }

运行结果:

addUser beginning...
a user added !
addUser ending...
deleteUser beginning...
a user deleted !
deleteUser ending...

User的addUser、deleteUser方法前后都加上了想要处理的业务逻辑,而源代码不用改变。

AOP用处:

权限、日志、审查、效率检查、异常管理。。。

最新文章

  1. 我的第二个FluentNHibernate例子with Knockout
  2. 12-rm 命令总结
  3. php操作redis常用方法源代码
  4. freemarker小例子
  5. HTML5 API 之 history
  6. python url编码,解码
  7. PL/pgSQL的RETURN QUERY例子
  8. Java语言基础(五) Java原始数据类型的分类以及数据范围
  9. 「Poetize3」Heaven Cow与God Bull
  10. 搜索(DLX): POJ 3074 3076 Sudoku
  11. LeetCode_Convert Sorted List to Binary Search Tree
  12. Java中String的split()方法的一些需要注意的地方
  13. vue评论显示隐藏,JavaScript显示关闭
  14. java获取本机ip地址(写出来的)
  15. Redis数据结构详解,五种数据结构分分钟掌握
  16. android 开发 View _3_ View的属性动画ValueAnimator
  17. C++11 constexpr常量表达式
  18. 用secureCRT操作ubuntu终端
  19. 【基础】selenium中元素定位的常用方法(三)
  20. Mingw编译DLib

热门文章

  1. RSA加密解密总结
  2. 监控小工具(jconsole)
  3. HRBUST1212 乘积最大 2017-03-06 15:47 59人阅读 评论(0) 收藏
  4. CodeForces - 589F —(二分+贪心)
  5. [转载]关于JAVA中子类和父类的构造方法
  6. JAVA常见面试题及解答
  7. C#基础入门 八
  8. mysql导入数据load data infile用法(转)
  9. Hadoopd 单元测试-MPUnit
  10. .Net上传图片压缩质量,不改变尺寸