<commit_before>---
layout: post
title: Java AOP和字节码增强技术
category: 编程语言
tags: Java
keywords: Java
description: Java AOP和字节码增强技术
---

### 静态代理和动态代理

在业务中执行一些公用的代理，如事务，日志记录，权限管理的代码，为了解耦和更好维护，通常使用代理的设计模式。

```java
public interface Subject   
{   
  public void doSomething();   
}
```

```java
public class RealSubject implements Subject   
{   
  public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
}  
```

```java
public class SubjectProxy implements Subject
{
  Subject subimpl = new RealSubject();
  public void doSomething()
  {
     subimpl.doSomething();
  }
}
```

```java
public static void main(String args[])
{
   Subject sub = new SubjectProxy();
   sub.doSomething();
}
```

静态代理这个模式本身有个大问题，如果类方法数量越来越多的时候，代理类的代码量是十分庞大的。所以引入动态代理来解决此类问题。

### 动态代理

```java
public class ProxyHandler implements InvocationHandler
{
    private Object tar;
    //绑定委托对象，并返回代理类
    public Object bind(Object tar)
    {
        this.tar = tar;
        //绑定该类实现的所有接口，取得代理类 
        return Proxy.newProxyInstance(tar.getClass().getClassLoader(),
                                      tar.getClass().getInterfaces(),
                                      this);
    }    
    public Object invoke(Object proxy , Method method , Object[] args)throws Throwable
    {
        Object result = null;
        //这里就可以进行所谓的AOP编程了
        //在调用具体函数方法前，执行功能处理
        result = method.invoke(tar,args);
        //在调用具体函数方法后，执行功能处理
        return result;
    }
}
```

```java
public static void main(String args[])
{
    ProxyHandler proxy = new ProxyHandler();
    //绑定该类实现的所有接口
    Subject sub = (Subject) proxy.bind(new RealSubject());
    sub.doSomething();
}
```

### 字节码增强技术

使用动态代理事项的 AOP，有几个缺陷：

* 它必须基于接口来实现，也就是代理的类必须要有接口，而且只能调用接口的方法，实例的其他方法无法访问。
* 方法之间的调用无法进行AOP，只有在外部调用这些方法时，才会调用代理的 invoke 方法。

除此之外，字节码增强技术有两种实现机制：

1.一种是通过原始类的子类，也就是动态创建这个类继承原来的类，现在的Spring AOP也正是通过这样的方式进行实现的，它们创建的子类通常以原始类的名称为前缀，再加上一个特定的后缀，以避免类名重复。
2.另外一种更加暴力，即直接修改原先的Class字节码，在许多类的跟踪过程中会使用到此技术。

实现字节码增强技术通过如下步骤：

1.在内存中获取原始的字节码，然后通过一些开源项目(ASM,CGBLIb,javassist)等修改它的byte[]数组，得到一个新的byte[]数组。
2.将这个新的byte[]数组写到PermGen区域，也就是加载它或者替换原来的Class字节码。


 
<commit_msg>Java AOP<commit_after>---
layout: post
title: Java AOP和字节码增强技术
category: 编程语言
tags: Java
keywords: Java
description: Java AOP和字节码增强技术
---

### 静态代理和动态代理

在业务中执行一些公用的代理，如事务，日志记录，权限管理的代码，为了解耦和更好维护，通常使用代理的设计模式。

```java
public interface Subject   
{   
  public void doSomething();   
}
```

```java
public class RealSubject implements Subject   
{   
  public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
}  
```

```java
public class SubjectProxy implements Subject
{
  Subject subimpl = new RealSubject();
  public void doSomething()
  {
     subimpl.doSomething();
  }
}
```

```java
public static void main(String args[])
{
   Subject sub = new SubjectProxy();
   sub.doSomething();
}
```

静态代理这个模式本身有个大问题，如果类方法数量越来越多的时候，代理类的代码量是十分庞大的。所以引入动态代理来解决此类问题。

### 动态代理

```java
public class ProxyHandler implements InvocationHandler
{
    private Object tar;
    //绑定委托对象，并返回代理类
    public Object bind(Object tar)
    {
        this.tar = tar;
        //绑定该类实现的所有接口，取得代理类 
        return Proxy.newProxyInstance(tar.getClass().getClassLoader(),
                                      tar.getClass().getInterfaces(),
                                      this);
    }    
    public Object invoke(Object proxy , Method method , Object[] args)throws Throwable
    {
        Object result = null;
        //这里就可以进行所谓的AOP编程了
        //在调用具体函数方法前，执行功能处理
        result = method.invoke(tar,args);
        //在调用具体函数方法后，执行功能处理
        return result;
    }
}
```

```java
public static void main(String args[])
{
    ProxyHandler proxy = new ProxyHandler();
    //绑定该类实现的所有接口
    Subject sub = (Subject) proxy.bind(new RealSubject());
    sub.doSomething();
}
```

### 字节码增强技术

使用动态代理事项的 AOP，有几个缺陷：

* 它必须基于接口来实现，也就是代理的类必须要有接口，而且只能调用接口的方法，实例的其他方法无法访问。
* 方法之间的调用无法进行AOP，只有在外部调用这些方法时，才会调用代理的 invoke 方法。

除此之外，字节码增强技术有两种实现机制：

1.一种是通过原始类的子类，也就是动态创建这个类继承原来的类，现在的Spring AOP也正是通过这样的方式进行实现的，它们创建的子类通常以原始类的名称为前缀，再加上一个特定的后缀，以避免类名重复。
2.另外一种更加暴力，即直接修改原先的Class字节码，在许多类的跟踪过程中会使用到此技术。

实现字节码增强技术通过如下步骤：

1.在内存中获取原始的字节码，然后通过一些开源项目(ASM,CGBLIb,javassist)等修改它的byte[]数组，得到一个新的byte[]数组。 
2.将这个新的byte[]数组写到PermGen区域，也就是加载它或者替换原来的Class字节码。


 

{'fraction_non_alphanumeric': 0.11348837209302326, 'fraction_numerical': 0.0018604651162790699, 'mean_word_length': 3.3488372093023258, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4610823', 'n_tokens_mistral': 2168, 'n_tokens_neox': 2331, 'n_words': 269}