前景提要

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

  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. C# Enum,Int,String,之间及bool与int之间的转换

    枚举类型的基类型是除 Char 外的任何整型,所以枚举类型的值是整型值. Enum 提供一些实用的静态方法: (1)比较枚举类的实例的方法 (2)将实例的值转换为其字符串表示形式的方法 (3)将数字的 ...

  2. SpringCloud系列十:使用Feign实现声明式REST调用

    1. 回顾 前文的示例中是使用RestTemplate实现REST API调用的,代码大致如下: @GetMapping("/user/{id}") public User fin ...

  3. 李洪强经典面试题51-KVO-KVC

    李洪强经典面试题51-KVO-KVC   KVC-KVO KVC的底层实现? 当一个对象调用setValue方法时,方法内部会做以下操作: ①检查是否存在相应key的set方法,如果存在,就调用set ...

  4. android studio中文乱码问题

    在build.gradle中加入代码: tasks.withType(JavaCompile) { options.encoding = "UTF-8" }

  5. 键值对集合 dict(字典)

    xx= { ss, ss } 创建字典 len(ss) 返回字典到长度,len函数可以返回任何集合的长度,list.tuple.dict都是集合的一种 什么是dict 我们已经知道,list 和 tu ...

  6. hdu1695 GCD2 容斥原理 求x属于[1,b]与y属于[1,d],gcd(x,y)=k的对数。(5,7)与(7,5)看作同一对。

    GCD Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): Accepted Sub ...

  7. 为什么Servlet修改之后,Tomcat都得重启,servlet才会生效!

    最近做东西经常需要重新加载项目,今天深深的问了自己为什么? Servlet的生命周期中,只会初始化一次,如果每次要是发送请求或响应,Servlet引擎都会调用service.从这里就会看出,servl ...

  8. String转int的几种常用方法

    String类型转int类型通常需要int的包装类Integer,该类有三个方法可以实现这种转换,分别为decode(String s).parseInt(String s).valueOf(Stri ...

  9. 我们可以用JAX-WS轻松实现JAVA平台与其他编程环境(.net等)的互操作

    在 JAX-WS中,一个远程调用可以转换为一个基于XML的协议例如SOAP,在使用JAX-WS过程中,开发者不需要编写任何生成和处理SOAP消息的代码.JAX-WS的运行时实现会将这些API的调用转换 ...

  10. Python 爬虫实战2 百度贴吧帖子

    爬取百度贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作. 本篇目标 对百度贴吧的任意帖子进行抓取 指定是否只抓取楼主发帖内容 将抓取到的内容分析并保存到文件 1.URL格式的确定 首先, ...