1、静态代理,实现代码如下,实际上是对装饰器模式的一种应用

interface UserManager {
public void addUser();
} class UserManagerImpl implements UserManager {
public void addUser() {
System.out.println("raw addUser");
}
} class UserManagerImplProxy implements UserManager {
private UserManager userManager; public UserManagerImplProxy(UserManager userManager) {
this.userManager = userManager;
} public void addUser() {
System.out.println("in proxy");
userManager.addUser();
}
}
public class ProxyTest {
public static void main(String args[]) {
UserManager userManager = new UserManagerImplProxy(new UserManagerImpl());
userManager.addUser();
}
}

2、动态AOP,借助 java.lang.reflect.InvocationHandler接口 和 java.lang.reflect.Proxy 类实现

java.lang.reflect.InvocationHandler接口的定义如下:

public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

Object proxy:被代理的对象

Method method:要调用的方法

Object[] args:方法调用时所需要参数

invoke 方法用于切面处理,调用相应的方法

java.lang.reflect.Proxy类的定义如下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

CLassLoader loader: 类的加载器

Class<?> interfaces: 得到全部的接口

InvocationHandler h: 实现 InvocationHandler 接口的子类的实例

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; interface UserManager {
public void addUser();
} class UserManagerImpl implements UserManager {
public void addUser() {
System.out.println("raw addUser");
}
} class UserManagerImplProxy implements InvocationHandler { private Object targetObject; public void log() {
System.out.println("message info");
} public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
log();
Object ret = method.invoke(targetObject, args);
return ret;
}
}
public class ProxyTest {
public static void main(String args[]) {
UserManagerImplProxy proxy = new UserManagerImplProxy();
UserManager manager = (UserManager) proxy.createProxyInstance(new UserManagerImpl());
manager.addUser();
}
}

3、动态代码字节生成

CGLib是动态代码字节生成的实现,它封装字节码生成工具Asm,原理是在运行期间目标字节码加载后,生成目标类的子类,将切面逻辑加入到子类中,所以使用Cglib实现AOP不需要基于接口。cglib 的核心是实现 MethodInterceptor 接口,使用 intercept() 方法进行面向切面的处理,调用相应的通知。其中 cglib 中有一个 Enhancer 类,可以使用他快速的创建一个代理类。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; interface UserManager {
public void addUser();
} class UserManagerImpl implements UserManager {
public void addUser() {
System.out.println("raw addUser");
}
} class CGLIBProxyFactory implements MethodInterceptor{
// 要放回的代理对象
private Object obj; public Object createProxy(Object obj) {
// 把传进来的代理对象赋值给obj
this.obj = obj;
Enhancer enhancer = new Enhancer();
// 需要为其实例指定一个父类,也就是我们 的目标对象,那么我们新创建出来的对象就是目标对象的子类,有目标对象的一样
enhancer.setSuperclass(this.obj.getClass());
// 除此之外,还要指定一个回调函数,这个函数就和Proxy的 invoke()类似
enhancer.setCallback(this);
return enhancer.create(); } public void log() {
System.out.println("message info");
} @Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object proxyObject = null;
UserManagerImpl um = (UserManagerImpl) obj;
log();
proxyObject = methodProxy.invoke(um, args);
return proxyObject;
} } public class ProxyTest {
public static void main(String args[]) {
CGLIBProxyFactory gb = new CGLIBProxyFactory();
UserManager manager = (UserManager)gb.createProxy(new UserManagerImpl());
manager.addUser();
}
}

AOP的实现的几种方式的更多相关文章

  1. 利用aop插入异常日志的2种方式

    AOP是面向切面编程,利用这个技术可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分的耦合性降低,提高代码的可重用性,同时提高开发效率(来自百度百科). Spring AOP有两种实现方式,一 ...

  2. Spring事务配置的五种方式(转载)

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSo ...

  3. Spring事务配置的五种方式

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSo ...

  4. 配置spring事务管理的几种方式(声明式事务)

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSo ...

  5. Spring事务配置的五种方式 -- 越往后需要Spring版本越高

    第五种 基本零配置  个人感觉第四种也可以 Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式, ...

  6. Spring 事务配置5种方式

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSo ...

  7. Spring事务配置的五种方式(转)

    前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...

  8. Spring事务配置的五种方式(转发)

    Spring事务配置的五种方式(原博客地址是http://www.blogjava.net/robbie/archive/2009/04/05/264003.html)挺好的,收藏转发 前段时间对Sp ...

  9. Spring事务配置的五种方式 巨全!不看后悔,一看必懂!

    前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...

随机推荐

  1. 201521123024 《Java程序设计》 第九周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己 ...

  2. ROS学习记录(四)————怎样建立一个package包?

    功能包是什么? 英文表述package,我可没有在炫英文啊,我的英文很烂的,只是在提醒大家,在ROS系统中,这个词使用的频率非常之高,你必须记住它,要不就没法正确的看懂信息.言归正传,package是 ...

  3. 举例让抽象问题具体化:包含min函数的栈

    定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数.在该栈中,调用min.push及pop的时间复杂度都是O(1). import java.util.Stack; public c ...

  4. JS中基本的一些兼容问题 可能解释的不会太清楚

    做兼容注意: 一如果两个都是属性,用逻辑||做兼容 二如果有一个是方法 用三目运算符做兼容 三多个属性或方法封装函数做兼容 一:谷歌浏览器和火狐浏览器鼠标滚动条兼容 1.document.docume ...

  5. multimap 和priority_queue详解

    上一期是关于STL和并查集结合的例题,也附了STL中部分容器的使用摘要,由于是从网上东拼西凑的,感觉有的关键点还是没解释清楚,现在从其中摘出两个容器,用例题对它们的用法进行进一步解释. 以下是例题的介 ...

  6. JAVA 并发(待补全!)

    从性能上看 如果没有任务会阻塞 那么在单处理器的机器人使用并发就没有任何意义 (需要上下文切换 时间反而长) 进程是运行在他自己地址空间的自包容的程序 协作多线程与抢占式多线程 想要定义任务需要实现R ...

  7. centos7.2 linux 64位系统上安装mysql

    1.在线安装mysql 在终端中命令行下输入(在官网下载mysql): # wget https://dev.mysql.com/downloads/repo/yum/mysql57-communit ...

  8. 关于高德地图Android开发时地图只显示一次、第二次打开不定位的解决办法

    我按照高德官方Demo改的 第一次是可以定位的,如左图 第二次就不能定位了,如右图 在onDestory中把aMap置为空即可 aMap = null; 修改完如下图: 原理是第二次打开时aMap不为 ...

  9. http://codeforces.com/contest/828

    哇这是我打的第一场cf,第一题都wa了无数次,然后第二题差几分钟交 ,第二天一交就AC了内心是崩溃的.果然我还是太菜l.... A. Restaurant Tables time limit per ...

  10. 通过修改 LayoutInflater,全局替换字体!!!

    序 在 Android 下使用自定义字体已经是一个比较常见的需求了,最近也做了个比较深入的研究. 那么按照惯例我又要出个一篇有关 Android 修改字体相关的文章,但是写下来发现内容还挺多的,所以我 ...