前景提要

  监控方法性能、执行时间、记录日志等

  AOP( Aspect Oriented Programming)面向方面编程。

  在AOP中,需要定义一个Aspect(切面)类来编写需要横切业务的逻辑代码,例如上面提到的性能监控代码。此外,还需要通过一个条件来匹配想要拦截的类,这个条件在AOP中称为PointCut(切点)。

技术点

  代理技术

  使用Spring提供的AOP技术

  使用动态代理技术实现AOP框架

  使用ThreadLocal技术

  数据库事物管理机制

  使用AOP框架实现事物控制

一、代理技术

  代理,Proxy。aop是代理的一种实现。Http代理等

1.1、静态代理

  示例  

public interface Hello {
void say(String name);
}

  实现

public class HelloImpl implements Hello {
@Override
public void say(String name) {
System.out.println("Hello! " + name);
}
}

  如,在说前后增加操作。

  初级代理实现:

public class HelloProxy implements Hello {
private Hello hello;
public HelloProxy() {
this.hello = new HelloImpl();
}
@Override
public void say(String name) {
before();
hello.say(name);
after();
}
private void before(){
System.out.println("Before");
}
private void after(){
System.out.println("After");
}
}

  测试主类:  

        Hello helloProxy = new HelloProxy();
helloProxy.say("muzixu");

  输出:

Before
Hello! muzixu
After

其实,以上helloProxy 就是代理。

1.2、JDK动态代理

第一次 编写

  使用JDK方案的一个动态代理

public class DynamicProxy implements InvocationHandler {
private Object target; public DynamicProxy(Object target) {
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target,args);
after();
return result;
} private void before(){
System.out.println("Before");
}
private void after(){
System.out.println("After");
}
}

  在DynamicProxy 类中定义了一个Object的target变量,他就是被代理的目标对象。通过构造函数来初始化【即注入】。

  该类实现了InvocationHandler 接口,需要实现的方法即invoke。在该方法中,直接通过反射去invoke method,在调用前后分别before,after,最后返回结果。

  调用

        Hello hello=new HelloImpl();
DynamicProxy dynamicProxy=new DynamicProxy(hello);
Hello helloProxy = (Hello)Proxy.newProxyInstance(hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(),
dynamicProxy);
helloProxy.say("muzixu");

  用通用的DynamicProxy 类去包装HelloImpl实例,然后在调用JDK提供的Proxy类的工厂方法newProxyInstance去动态的创建一个Hello接口的代理类,最后调度用这个代理类的方法。

  结果同上一致。

第二次 优化  

public class DynamicProxy2 implements InvocationHandler {
private Object target; public DynamicProxy2(Object target) {
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
} public <T> T getProxy() {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
} private void before() {
System.out.println("Before");
} private void after() {
System.out.println("After");
}
}

  使用

        DynamicProxy2 dynamicProxy=new DynamicProxy2(new HelloImpl());
Hello helloProxy = dynamicProxy.getProxy();
helloProxy.say("muzixu");

其实就是将实例化过程抽象。

对比一下

名称 优点 缺点
静态代理   接口变了,实现类需要变,代理类也要变
JDK动态代理 接口变了,代理类不变 无法代理没有实现任何一个接口的类
CGlib动态代理

运行期间动态生成字节码的工具

也就是动态生成代理类

 

1.3、CGlib动态代理

  spring,hibernate等使用

  pom:

    <dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
</dependencies>

第一次实例

public class CGLibProxy implements MethodInterceptor {
public <T> T getProxy(Class<T> cls) {
return (T) Enhancer.create(cls,this);
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object result = methodProxy.invokeSuper(o,objects);
after();
return result;
}
private void before() {
System.out.println("Before");
} private void after() {
System.out.println("After");
}
}

  使用

        CGLibProxy proxy = new CGLibProxy();
Hello hello = proxy.getProxy(HelloImpl.class);
hello.say("muzixu");

第二次 单例模式构建

public class CGLibSingleProxy implements MethodInterceptor {
private static CGLibSingleProxy instance = new CGLibSingleProxy();
private CGLibSingleProxy(){
}
public static CGLibSingleProxy getInstance(){
return instance;
}
public <T> T getProxy(Class<T> cls) {
return (T) Enhancer.create(cls,this);
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object result = methodProxy.invokeSuper(o,objects);
after();
return result;
}
private void before() {
System.out.println("Before");
} private void after() {
System.out.println("After");
}
}

  调用

        Hello hello = CGLibSingleProxy.getInstance().getProxy(HelloImpl.class);
hello.say("muzixu");

004-搭建框架-实现AOP机制【一】代理技术的更多相关文章

  1. Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架

    类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader 类加载器也是Jav ...

  2. 005-搭建框架-实现AOP机制【二】AOP技术

    一.什么是AOP aspect-oriented  programming,面向切面编程,对oop的一种补充. 著名示例,aspectj,spring+aspectj 二.aop之代码重构 2.1.代 ...

  3. SSM框架之AOP、动态代理、事务处理相关随笔

    AOP: 原理:底层利用动态代理(两种动态代理技术都使用了) 两种实现方案: 第一种:JDK动态代理技术 实现的InvocationHandler接口,要想实现某个类的动态代理对象,必须有接口有实现类 ...

  4. Spring AOP 和 动态代理技术

    AOP 是什么东西 首先来说 AOP 并不是 Spring 框架的核心技术之一,AOP 全称 Aspect Orient Programming,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...

  5. 006-搭建框架-实现AOP机制【三】AOP技术

    2.3.spring+aspectj Spring在集成了aspectj后,同时也保留了以上的切面与代理的配置方式. 将Spring与aspectj集成与直接使用aspectj不同,不需要定义Aspe ...

  6. Castle框架中的IOC和AOP机制

    反转控制(IOC)和面向切面编程(AOP)技术作为当前比较流行的技术,其优势已受到广泛关注,但是这两项新技术在实际项目上的应用研究却很落后,而且在.NET平台下实现这两项技术没有形成可以广泛套用的框架 ...

  7. [Spring框架]Spring AOP基础入门总结一.

    前言:前面已经有两篇文章讲了Spring IOC/DI 以及 使用xml和注解两种方法开发的案例, 下面就来梳理一下Spring的另一核心AOP. 一, 什么是AOP 在软件业,AOP为Aspect ...

  8. 架构探险笔记5-使框架具备AOP特性(下)

    开发AOP框架 借鉴SpringAOP的风格,写一个基于切面注解的AOP框架.在进行下面的步骤之前,确保已经掌了动态代理技术. 定义切面注解 /** * 切面注解 */ @Target(Element ...

  9. 10.Spring——框架的AOP

    1.Spring 框架的 AOP 2.Spring 中基于 AOP 的 XML架构 3.Spring 中基于 AOP 的 @AspectJ 1.Spring 框架的 AOP Spring 框架的一个关 ...

随机推荐

  1. SQL Server事务详解

    事务定义: 事务是单个的工作单元.如果某一事务成功,则在该事务中进行的所有数据更改均会提交,成为数据库中的永久组成部分.如果事务遇到错误且必须取消或回滚,则所有数据更改均被清除. 事务三种运行模式:  ...

  2. mac下使用QuickTime录屏及上传youku注意事项

    一,解决QuickTime录屏不能带声音的问题: mac下使用QuickTime屏幕 Soundflower->Audio Setup->soundflower(2ch),在其上鼠标右键, ...

  3. spring 第一篇(1-1):让java开发变得更简单(上)

    1.释放POJOS能量 传统开发中是如何束缚POJOS呢,如果你开发过java很长时间,那你一定有接触过EJB的开发.那时候开发一个小小的功能都要扩展框架的类或者实现其接口.所以你很容易在早期的Str ...

  4. 程序的记事本--log4net

    你是否在遇到程序执行问题时常常百度?你是否在遇到执行错误时常常去询问别人?假设有那么是时候改变啦,对于一个Developer来说那是不专业的表现,专业的Developer都会首先查看程序的执行日志.先 ...

  5. ES6 学习笔记 (1)

    笔记来源:廖雪峰老师的javascript全栈教程 ES6:JavaScript的标准,ECMAScript在不断发展,最新版ECMAScript 6标准(简称ES6)已经在2015年6月正式发布了, ...

  6. 更改系统环境设置,让alias永远生效

        alias(中文称为“别名”)允许使用更加简短的名称来重新定义 Linux 中的 Shell 命令,从而简化命令行的输入.如果经常与 CLI 打交道,那么使用 alias 不仅会节省时间,而且 ...

  7. python django -1

    VT Django是一款python的web开发框架 与MVC有所不同,属于MVT框架 m表示model,负责与数据库交互 v表示view,是核心,负责接收请求.获取数据.返回结果 t表示templa ...

  8. 关于 SQLNET.AUTHENTICATION_SERVICES 验证方式的说明

    今天去客户那里巡检,客户提出为了提高数据库安全性考虑,须要改动sys/systempassword,并通过数据库验证方式来代替默认的操作系统方式,如今我来把这两种验证方式总结一下. 操作系统验证.即通 ...

  9. Python中threading的join和setDaemon的区别及用法[例子]

    Python多线程编程时,经常会用到join()和setDaemon()方法,今天特地研究了一下两者的区别. 1.join ()方法:主线程A中,创建了子线程B,并且在主线程A中调用了B.join() ...

  10. Python Socket套接字

    socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Un ...