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. 201521145048 《Java程序设计》第7周学习总结

    1. 本周学习总结 2. 书面作业 Q1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 1.2 解释E remove(int index)源代码 1.3 结合1. ...

  2. 201521123032 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出 ...

  3. 201521123026 《java程序设计》 第九周学习总结

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

  4. 201521123070《Java程序设计》 第11周学习总结

    本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 书面作业 本次PTA作业题集多线程 互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1.1 除了使用 ...

  5. .net core 使用Redis的发布订阅

    Redis是一个性能非常强劲的内存数据库,它一般是作为缓存来使用,但是他不仅仅可以用来作为缓存,比如著名的分布式框架dubbo就可以用Redis来做服务注册中心.接下来介绍一下.net core 使用 ...

  6. 聊聊JAVA中 String类为什么不可变

    前言 "我的风格比较偏传统和经典" 小明说,"我们在打扮自己的问题上还是蛮冒险的...我觉得当你是只狗的时候,穿什么都hold的住!" 哈哈哈,脱离单身狗快两年 ...

  7. birt IE8 IE9 兼容问题

    我自己的应用,birt展示报表的时候,在firefox和IE下显示的样式: IE8下的: Firefox下的: 我的项目,应用birt部分的结构如下: 1, prototype.js ,查找下面这段代 ...

  8. Mysql中的like模糊查询

    MySql的like语句中的通配符:百分号.下划线和escape %代表任意多个字符 _代表一个字符 escape,转义字符后面的%或_,使其不作为通配符,而是普通字符匹配   数据库数据如下: 1. ...

  9. [err] 1055

    本人mysql安装在ubuntu16.04上,mysql版本是5.7.19:在创建表和插入数据时报了 [Err] 1055 - Expression #1 of ORDER BY clause is ...

  10. Redis学习——Redis持久化之RDB备份方式保存数据

    从这一个介绍里面知道,redis比memcache作为缓存数据库强大的地方,一个是支持的数据类型比较多,另一个就是redis持久化功能. 下面就介绍Redis的持久化之RDB! 一:什么是redis的 ...