java_Proxy动态代理_AOP
讲了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用处:
权限、日志、审查、效率检查、异常管理。。。
java_Proxy动态代理_AOP的更多相关文章
- java动态代理_aop
(一)代理概述 1.问题:要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理.日志.计算方法的运行时间.事务管理等等,如何去做? 解答:编写一个与目标类具有相同接口的代理类 ...
- JDK动态代理
一.基本概念 1.什么是代理? 在阐述JDK动态代理之前,我们很有必要先来弄明白代理的概念.代理这个词本身并不是计算机专用术语,它是生活中一个常用的概念.这里引用维基百科上的一句话对代理进行定义: A ...
- AOP之Castle DynamicProxy 动态代理
这里主要介绍使用castle这个动态代理,在.net一些开源的框架里可以找到它的影子,就连微软的rchard也是使用这个进行方法拦截等可以基于这个进行方法拦截,在这个方面PostSharp算是比较好用 ...
- java动态代理的2种实现方式
java的动态代理在接java的api上有说明,这里就不写了.我理解的代理: 对特定接口中特定方法的功能进行扩展,这就是代理.代理是通过代理实例关联的调用处理程序对象调用方法. 下面通过一个例子看一下 ...
- JDK动态代理实现原理
之前虽然会用JDK的动态代理,但是有些问题却一直没有搞明白.比如说:InvocationHandler的invoke方法是由谁来调用的,代理对象是怎么生成的.直到看了他的文章才彻底明白,附网址:htt ...
- java中动态代理的实现
动态代理的实现 使用的模式:代理模式. 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.类似租房的中介. 两种动态代理: (1)jdk动态代理,jdk动态代理是由Java内部的反射机制 ...
- 静态代理和利用反射形成的动态代理(JDK动态代理)
代理模式 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 静态代理 1.新建 ...
- Java动态代理
代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关 ...
- Java 动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
随机推荐
- ASP.NET Core2使用Autofac实现IOC依赖注入竟然能如此的优雅简便
初识ASP.NET Core的小伙伴一定会发现,其几乎所有的项目依赖都是通过依赖注入方式进行链式串通的.这是因为其使用了依赖注入 (DI) 的软件设计模式,代码的设计是遵循着“高内聚.低耦合”的原则, ...
- SQL Server创建表超出行最大限制解决方法
问题的现象在创建表A的时候,出现“信息 511,级别 16,状态 1,第 5 行 无法创建大小为 的行,该值大于允许的最大值 8060.”的信息提示.很奇怪,网上查了一下,是因为要插入表的数据类型的 ...
- jenkins修改时区
查看jenkins目前的时区 访问http://your-jenkins/systemInfo,查看user.timezone变量的值 默认是纽约时间 修改时区 查https://wiki.jenki ...
- ASP.NET 常用的字符串加密
字符串常用的加密有三种 1.MD5加密,这个常用于密码,单向加密,不可解密,有些在线解密的可以解大部份,用代码不能实现,如果不想让人解密,加密后随便截取一段就好了: 2.Base64位加密,通常加密后 ...
- HTML5 LocalStorage Demo
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- IOS渠道追踪方式
本文来自网易云社区 作者:马军 IOS,安卓渠道追踪的差异 Google Play国内不可用,国内的安卓 App 分发,都是依托几十个不同的应用市场或发行渠道,如百度.360.腾讯等互联网企业以及小米 ...
- WordPress插件Social Warfare<=3.5.2 无需登录RCE漏洞
该漏洞只存在于Social Warfare插进的3.5.0.3.5.1和3.5.2版本中,其他版本不存在. 2019年3月21日插件作者紧急发布了3.5.3版本以修复高危的RCE漏洞,在<=3. ...
- ceph pg_num 数值计算
通常在创建pool之前,需要覆盖默认的pg_num,官方推荐: 若少于5个OSD, 设置pg_num为128. 5~10个OSD,设置pg_num为512. 10~50个OSD,设置pg_num为40 ...
- 2018-2019-2 20165219《网络对抗技术》Exp4 恶意代码分析
基础问题回答 实验目的 监控系统的运行状态,看有没有可疑的程序在运行 分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysinternals,systracer套 ...
- “全栈2019”Java第一百零二章:哪些作用域可以声明局部内部类?
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...