### 本文由博主柒。原创,转载请注明出处

### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/MatrixSeven/JavaAOP)
一说到AOP,大家一定会想到Spring,因为这东西实在是太强大了.但是大家一定要清楚,AOP是一只编程思想,而Spring仅仅是AOP的一种实现罢了.

首先百度下:

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

如果你对AOP还没有了解请左移百度百科:[http://baike.baidu.com/search/word?word=AOP](http://baike.baidu.com/search/word?word=AOP查看)查看.

今天呢,咱们就一起用Java原生代理实现简单的AOP功能.

首先,你得需要了解基本的反射知识,否则可能会感到困惑.

不罗嗦了,直接开始撸码

首先,咱们先写一个简单的接口.名字叫AnimalInterface,用来声明规范动物的一些基本方法.

这些方法包括 设置名字,获取名字,叫声,属性(原谅我没文化,其实就是获得是陆栖还是水栖或者水陆两栖)

```Java
package proxy.imp;
public interface AnimalInterface {
//设置名字
void setName(String name);
//获取名字
String getName();
//叫声
void say();
//获取栖性
void getProperty();
}
```
然后咱们实现这个接口,创建一个名叫小黑的Dog
```Java
package proxy;

import proxy.imp.AnimalInterface;
public class DogImp implements AnimalInterface {
private String name = "小黑";
public DogImp() {
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public void say() {
System.out.println("小狗:汪汪汪汪.....");
}
@Override
public void getProperty() {
System.out.println("小狗是陆地动物,但是会游泳哦");
}
}
```
大家一定迫不及待了,怎么实现类似AOP的功能呢….

咱们先创建一个名为AOPHandle的类,让其实现InvocationHandler接口,

不能使用invoke时使用proxy作为反射参数时,因为代理对象的接口,不同于对象,

这种代理机制是面向接口,而不是面向类的,如果使用proxy,会造成无限递归.然后就是栈溢出,但是依旧能反射成功一次,

这说明代理对象和对象的代理是不一样的,但是咱们可以通过proxy参数的proxy.getClass()获得class对象,然后获得被代理

类的方法和参数,这也为注解注入,特定方法注入,属性注入提供了一种实现途径吧,关于这个,咱们后面再说..

```Java
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class AOPHandle implements InvocationHandler{
//保存对象
private Object o;
public AOPHandle(Object o) {
this.o=o;
}
/**
* 这个方法会自动调用,Java动态代理机制
* 会传入下面是个参数
* @param Object proxy 代理对象的接口,不同于对象
* @param Method method 被调用方法
* @param Object[] args 方法参数
* 不能使用invoke时使用proxy作为反射参数时,因为代理对象的接口,不同于对象
* 这种代理机制是面向接口,而不是面向类的
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法返回值
Object ret=null;
//打印方法名称
System.err.println("执行方法:"+method.getName()+"n参数类型为:");
//打印参数
for(Class type:method.getParameterTypes())
System.err.println(type.getName());
//打印返回类型
System.err.println("返回数据类型:"+method.getReturnType().getName());
//反射调用方法
ret=method.invoke(o, args);
//声明结束
System.err.println("方法执行结束");
//返回反射调用方法的返回值
return ret;
}
}
```
动态代理已经搞定..然后就是咱们的AnimalFactory了..咱们继续

```java
package proxy;
import java.lang.reflect.Proxy;
public class AnimalFactory {
/***
* 获取对象方法
* @param obj
* @return
*/
private static Object getAnimalBase(Object obj){
//获取代理对象
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), new AOPHandle(obj));
}
/***
* 获取对象方法
* @param obj
* @return
*/
@SuppressWarnings("unchecked")
public static T getAnimal(Object obj){
return (T) getAnimalBase(obj);
}
/***
* 获取对象方法
* @param className
* @return
*/
@SuppressWarnings("unchecked")
public static T getAnimal(String className){
Object obj=null;
try {
obj= getAnimalBase(Class.forName(className).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
return (T)obj;
}
/***
* 获取对象方法
* @param clz
* @return
*/
@SuppressWarnings("unchecked")
public static T getAnimal(Class clz){
Object obj=null;
try {
obj= getAnimalBase(clz.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
return (T)obj;
}
}
```
终于到最后了…还差什么呢,大家来这里看看效果吧…

哈哈…小二,上个菜..哦~不对,是个测试类..哈哈////
```java
package proxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import proxy.AnimalFactory;
import proxy.imp.AnimalInterface;

@RunWith(BlockJUnit4ClassRunner.class)
public class AOPTest {

@Test
public void Test1() {
AnimalInterface dog=AnimalFactory.getAnimal(DogImp.class);
dog.say();
System.out.println("我的名字是"+dog.getName());
dog.setName("二狗子");
System.out.println("我的名字是"+dog.getName());
}
}
```
对,咱们的效果已经看到了..
,咦,你会说没图没真相???
好,那就上图…
```java
图片在sae上已经丢失,请大家脑补
```
啥?什么,,到了最后说,,这又卵用,这不是坑爹么?就捕获一个这个玩意,什么用啊…
什么AOP,我怎么一点AOP的影子都没有看到,怎么切入自定义方法,就一个syso输入,往这忽悠观众来了?…..
好吧,那咱们继续…看看如何实现注入自定义方法…

首先增加一个接口,咱们就称为AOP注入接口吧.取名AOPMethod哈
创建after和before方法,接收Object proxy, Method method, Object[] args参数
这样就能做更多的事情叻…比如执行方法前,记录类状态,写入log.监控xx变量,,,
开启你的脑洞吧.

```java
package proxy.imp;
import java.lang.reflect.Method;

public interface AOPMethod{
//实例方法执行前执行的方法
void after(Object proxy, Method method, Object[] args);
//实例方法执行后执行的方法
void before(Object proxy, Method method, Object[] args);
}
```
然后修改AOPHandle类,增加AOPMethod属性.

在修改构造方法,让在类初始化时获得AOPMethod实例.

最后修改invoke方法….直接上代码哈

```java
package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import proxy.imp.AOPMethod;

public class AOPHandle implements InvocationHandler{
//保存对象
private AOPMethod method;
private Object o;
public AOPHandle(Object o,AOPMethod method) {
this.o=o;
this.method=method;
}
/**
* 这个方法会自动调用,Java动态代理机制
* 会传入下面是个参数
* @param Object proxy 代理对象的接口,不同于对象
* @param Method method 被调用方法
* @param Object[] args 方法参数
* 不能使用invoke时使用proxy作为反射参数时,因为代理对象的接口,不同于对象
* 这种代理机制是面向接口,而不是面向类的
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object ret=null;
//修改的地方在这里哦
this.method.before(proxy, method, args);
ret=method.invoke(o, args);
//修改的地方在这里哦
this.method.after(proxy, method, args);
return ret;
}
}
```
呼呼,大功告成,,看起来一切都么问题,萌萌哒..

赶紧更新下测试类…
```java
package proxy;

import java.lang.reflect.Method;

import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import proxy.imp.AOPMethod;
import proxy.imp.AnimalInterface;

@RunWith(BlockJUnit4ClassRunner.class)
public class AOPTest {

public static void main(String[] args) {

AnimalInterface dog = AnimalFactory.getAnimal(DogImp.class, new AOPMethod() {
// 这里写方法执行前的AOP切入方法
public void before(Object proxy, Method method, Object[] args) {
System.err.println("我在" + method.getName() + "方法执行前执行");
}

// 这里系方法执行后的AOP切入方法
public void after(Object proxy, Method method, Object[] args) {
System.err.println("我在 " + method.getName() + "方法执行后执行");

}
});
dog.say();
String name1="我的名字是" + dog.getName();
System.out.println(name1);
dog.setName("二狗子");
String name2="我的名字是"+dog.getName();
System.out.println(name2);
}
}
```
来个效果图:
```java
图片在sae上已经丢失,请大家脑补
```
呼呼,亲们,是不是有注入的感觉了?是不是感觉把自己的方法切进去了???哈哈….

看起来一切都已经完美了,但是总觉得差了点什么?哦,对,缺少了类似于Spring那么样的配置文件..

其实那些已经很简单了,交给你们去做吧,设计好XML格式化就妥了,等等,你说什么,还不能拦截自定义方法?

不能像Spring那样拦截自定义方法?oh~~NO,其实已经可以了在
before(Object proxy, Method method, Object[] args)
中利用method和的给methodName就能做判断了.
当然,本例的并没有什么实用意义,更不能个各种完善的AOP框架相比,本文仅仅为您提供一种思路,但是一定要记住,再牛的东西也是一点点积累出来的
学习了解原理,是为了更好的驾驭所掌握的知识和技能.咱再会回嘿嘿.

使用Java原生代理实现AOP的更多相关文章

  1. 使用Java原生代理实现数据注入

    本文由博主原创,转载请注明出处 完整源码下载地址 https://github.com/MatrixSeven/JavaAOP 上一篇,咱们说了使用Java原生代理实现AOP的简单例子,然么就不得不说 ...

  2. Java动态代理-->Spring AOP

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓“登高必自卑,涉远必自迩”.以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系列分别介绍这些Jav ...

  3. Java 动态代理与AOP

    动态代理与AOP 代理模式 代理模式给某一个目标对象(target)提供代理对象(proxy),并由代理对象控制对target对象的引用. 模式图: 代理模式中的角色有: 抽象对象角色(Abstrac ...

  4. Java 动态代理及AOP实现机制

    AOP实现机制http://www.iteye.com/topic/1116696 AOP: (Aspect Oriented Programming) 面向切面编程AOP包括切面(aspect).通 ...

  5. [JAVA]动态代理与AOP的千丝万缕

    动态代理与AOP的联系 别的不说,直接上图 首先是AOP切面编程 什么是切面?(自己心里想想就ok)所以所谓的切面编程,你也就懂得大体了,只是这个被切的是个程序而已 那么AOP与动态代理有什么关系呢? ...

  6. Java动态代理(AOP)

    目录 一.代理 1. 什么是代理? 2. 使用代理模式的作用 3. 实现代理的方式 二.静态代理 1. 模拟用户购买u盘 2. 静态代理的缺点 三.动态代理 四. JDK 动态代理 1. Invoca ...

  7. Java动态代理学习【Spring AOP基础之一】

    Spring AOP使用的其中一个底层技术就是Java的动态代理技术.Java的动态代理技术主要围绕两个类进行的 java.lang.reflect.InvocationHandler java.la ...

  8. java动态代理实现与原理详细分析(代码层面解释了AOP的实现)

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式, ...

  9. AOP面向切面编程JAVA动态代理实现用户权限管理(实现篇)

    java动态代理机制的功能十分强大,使用动态代理技术能够有效的降低应用中各个对象之间的耦合紧密程度,提高开发的效率以及程序的可维护性,事实上Spring AOP就是建立在Java动态代理的基础之上.其 ...

随机推荐

  1. python核心编程第二版练习题答案

    2-5 #写一个while循环,输出整型为0~10 a=0while a<11: print a a+=1 #写一个for循环重复以上操作 for i in range(11): print i ...

  2. TDD在Unity3D游戏项目开发中的实践

    0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...

  3. 小兔JS教程(四)-- 彻底攻略JS数组

    在开始本章之前,先给出上一节的答案,参考答案地址: http://www.xiaotublog.com/demo.html?path=homework/03/index2 1.JS数组的三大特性 在J ...

  4. RSA非对称加密,使用OpenSSL生成证书,iOS加密,java解密

    最近换了一份工作,工作了大概一个多月了吧.差不多得有两个月没有更新博客了吧.在新公司自己写了一个iOS的比较通用的可以架构一个中型应用的不算是框架的一个结构,并已经投入使用.哈哈 说说文章标题的相关的 ...

  5. PHP 设计模式概述

    一.设计模式(Design pattern)是什么? 设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. ...

  6. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  7. Three.JS 从世界坐标系转换到屏幕坐标系

    var projector = new THREE.Projector(); var world_vector = new THREE.Vector3(0,0,1); var vector = pro ...

  8. 2016/12/28_javascript

    今天学习的主要内容: javascript: 1.if语句,switch语句,while循环以及for循环: 1)if语句 if(boolean){}; if(boolean){} else if(b ...

  9. iOS7 NavigationController 手势问题

    在iOS7中,如果使用了UINavigationController,那么系统自带的附加了一个从屏幕左边缘开始滑动可以实现pop的手势.但是,如果自定义了navigationItem的leftBarB ...

  10. Set up VLAN (802.1q) tagging on a network interface?

    SOLUTION VERIFIED October 13 2015 KB39674 KB741413 environment Red Hat Enterprise Linux 4 Red Hat En ...