`

3种方式实现AOP

 
阅读更多

一、代理模式实现aop

1
2
3
4
5
6
7
8
9
10
public interface IHello {
    void sayHello(String name);
}
 
public class Hello implements IHello {
    @Override
    public void sayHello(String name) {
          System.out.println(name+" say hello");
    }
}

  代理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class HelloProxy implements IHello {
 
    private IHello hello;
 
    public HelloProxy(IHello hello){
        this.hello=hello;
    }
    @Override
    public void sayHello(String name) {
        System.out.println("before....");
        hello.sayHello(name);
        System.out.println("after....");
    }
}

   客户端

1
2
3
4
5
6
7
public class Test {
 
    public static void main(String[] args){
        IHello hello=new HelloProxy(new Hello());
        hello.sayHello("persia");
    }
}

 

二、JDK的动态代理反射实现aop

    JDK动态代理只能代理接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * 使用JDK提供的动态代理
 * @author scipio
 * @created 2013-10-21
 */
public class DynaProxyHello implements InvocationHandler{
 
    private Object target;
 
 
    //动态生成代理对象
    public Object bind(Object target){
        this.target=target;
        return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),this.target.getClass().getInterfaces(),this);
    }
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before..... ");
         Object result=method.invoke(target,args);
        System.out.println("after.....");
        return result;
    }
}

   客户端

1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
 
    public static void main(String[] args){
        /**
         * 只能代理接口
         */
        IHello hello= (IHello) new DynaProxyHello().bind(new Hello());
//        Hello hello = (Hello) new DynaProxyHello().bind(new Hello());
        hello.sayHello("persia");
 
    }
}

 

三、Aspect方式(JDK实现)

  1、定义拦截后要执行的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * 拦截指定方法后要执行的方法
 * @author scipio
 * @created 2013-10-21
 */
public class CrossCutting {
 
    public void before(){
        System.out.println("before...");
    }
 
    public void after(){
        System.out.println("after...");
    }
 
}

2、模拟Aop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
 * 使用java的反射
 * 进行aop功能的模拟
 * @author scipio
 * @created 2013-10-21
 */
public class Aop {
 
    private static CrossCutting cut=new CrossCutting();
    private static ReflectUtils rfBefore=new ReflectUtils(cut,"before");
    private static ReflectUtils rfAfter=new ReflectUtils(cut,"after");
 
    public static void beforeAdvice(Object target,String methodName,Object ... params){
        Class cls=target.getClass();
        Method[] methods=cls.getDeclaredMethods();
        for(int i=0;i<methods.length;i++){
            if(methods[i].getName().equals(methodName)){
                rfBefore.invokeMethod();
                new ReflectUtils(target,methodName,params).invokeMethod();
            }
        }
    }
 
    public static void afterAdvice(Object target,String methodName,Object... params){
        Class cls=target.getClass();
        Method[] methods=cls.getDeclaredMethods();
        for(int i=0;i<methods.length;i++){
            if(methods[i].getName().equals(methodName)){
                new ReflectUtils(target,methodName,params).invokeMethod();
                rfAfter.invokeMethod();
 
            }
        }
    }
 
    public static void aroundAdvice(Object target,String methodName,Object... params){
        Class cls=target.getClass();
        Method[] methods=cls.getDeclaredMethods();
        for(int i=0;i<methods.length;i++){
            if(methods[i].getName().equals(methodName)){
                rfBefore.invokeMethod();
                new ReflectUtils(target,methodName,params).invokeMethod();
                rfAfter.invokeMethod();
 
            }
        }
    }
 
}

3、拦截对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * 要被拦截的方法
 * @author scipio
 * @created 2013-10-21
 */
public interface Crud {
    public void add(String user);
    public void modify(String user);
    public void delete(String user);
}
 
/**
 * 要被拦截的方法
 * @author scipio
 * @created 2013-10-21
 */
public class CrudImpl implements Crud {
    @Override
    public void add(String user) {
        System.out.println("new user:");
    }
 
    @Override
    public void modify(String user) {
         System.out.println("modify user");
    }
 
    @Override
    public void delete(String user) {
        System.out.println("delete user");
    }
}

4、客户端及工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class Test {
    public static void main(String[] args){
        Crud crud=new CrudImpl();
        Aop.beforeAdvice(crud,"modify","persia");
    }
}
 
/**
 * java反射的一些帮助方法
 * 通过传入的类,拦截要执行的方法名
 * 返回后直接invoke即可
 * 具体见aop
 * 无其他意义,不是经典模式,可以去掉
 * @author scipio
 * @created 2013-10-21
 */
public class ReflectUtils {
 
    private Class targetClass;
    private Object target;
    private Method targetMethod;
    private Object[] params;
 
    public ReflectUtils(Object target,String methodName,Object ... params){
        this.target=target;
        this.targetClass=target.getClass();
        this.params=params;
        Class[] cls=new Class[params.length];
        for(int i=0;i<params.length;i++){
            cls[i]=params[i].getClass();
        }
        try {
            this.targetMethod=targetClass.getMethod(methodName,cls);
        catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
 
    public void invokeMethod(){
        try {
            this.targetMethod.invoke(target,params);
        catch (IllegalAccessException e) {
            e.printStackTrace();
        catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

 

四、Aspect方式(Cglib实现)

1、拦截后要执行的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * 通过cglib进行拦截
 * @author scipio
 * @created 2013-10-21
 */
public class AroundCutting implements MethodInterceptor{
 
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before...."+method);
        //直接invoke会造成stack over flow
//        Object result = proxy.invoke(o, args);
        Object result = proxy.invokeSuper(o, args);
        System.out.println("after..."+method);
        return result;
    }
 
}

2、Cglib模拟aop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
 * cglib实现aop
 * @author scipio
 * @created 2013-10-21
 */
public class CglibAOP {
 
    private Enhancer enhancer = new Enhancer();
 
    /**
     * 使用Cglib进行动态代理,是创建一个子类继承至目标类,所以不需要像GDK动态代理那样提供一个接口,这样节约了类的个数。
     * JDK动态代理的特点:不能代理类,只能代理接口
     * CGLIB动态代理的特点:能代理类和接口,不能代理final类
     *  动态代理的本质:用来实现对目标对象进行增强,最终表现为类,只不过是动态创建子类,不用手工生成子类。
     * @param clz
     * @return
     */
 
    private MethodInterceptor interceptor;
 
    public CglibAOP(MethodInterceptor interceptor){
        this.interceptor=interceptor;
    }
 
    public Object getProxy(Class clz){
        //生成指定类对象的子类,也就是重写类中的业务函数
        enhancer.setSuperclass(clz);
        //这里是回调函数,加入intercept()函数
        enhancer.setCallback(interceptor);
        //创建这个子类对象
        return enhancer.create();
    }
 
 
}

3、被拦截对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * 要被拦截的方法
 * @author caibosi
 * @created 2013-10-21
 */
public class CrudImpl {
 
    public void add(String user) {
        System.out.println("new user:");
    }
 
    //用static方法的话,则拦截不了
    public void modify(String user) {
         System.out.println("modify user"+user);
    }
 
 
    public void delete(String user) {
        System.out.println("delete user");
    }
}

4、客户端

1
2
3
4
5
6
7
8
public class Test {
 
    public static void main(String[] args){
         CglibAOP aop=new CglibAOP(new AroundCutting());
         CrudImpl crud= (CrudImpl) aop.getProxy(CrudImpl.class);
         crud.modify("modify name");
    }
}

5、高级回调功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
 * cglib callback filter
 * 根据不同方法进行不同的拦截
 * @author scipio
 * @created 2013-10-24
 */
public class CglibCallbacks {
 
    public static void main(String[] args){
        //声明cglib增强类
        Enhancer enhancer = new Enhancer();
        //设置被代理类
        enhancer.setSuperclass(CrudImpl.class);
        //set callbacks
        Callback[] callbacks = new Callback[]{
              NoOp.INSTANCE,new AddCallback(),new ModifyCallback(),new DeleteCallback()
        };
        //设定拦截方法
        enhancer.setCallbacks(callbacks);
        //设定方法对应的拦截
        enhancer.setCallbackFilter(new DaoFilter());
        //通过增强类获取代理类
        CrudImpl proxyCrud = (CrudImpl)enhancer.create();
        proxyCrud.modify("persia");
        proxyCrud.add("linda");
        proxyCrud.delete("susan");
 
    }
}
 
class AddCallback implements MethodInterceptor{
 
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before....cutting add method");
        Object result = proxy.invokeSuper(o, args);
        System.out.println("after...cutting add method");
        return result;
    }
}
class ModifyCallback implements MethodInterceptor{
 
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before....cutting modify method");
        Object result = proxy.invokeSuper(o, args);
        System.out.println("after...cutting modify method");
        return result;
    }
}
 
class DeleteCallback implements MethodInterceptor{
 
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before....cutting delete method");
        Object result = proxy.invokeSuper(o, args);
        System.out.println("after...cutting delete method");
        return result;
    }
}
 
/**
 * 此方法用来决定哪个方法
 * 被那个callback拦截
 * 返回index,对应callbacks数组
 */
class DaoFilter implements CallbackFilter{
 
    @Override
    public int accept(Method method) {
        String methodName = method.getName();
        System.out.println("method:"+methodName);
        if(methodName.equals("delete")){
             return 3;
        }else if(methodName.equals("add")){
             return 1;
        }else if (methodName.equals("modify")){
             return 2;
        }
        //0对应了NoOp.INSTANCE的callback,表示不做任何事情
        return 0;
    }
}

 

五、要点

1、JDK只能基于接口动态代理

2、Cglib基于接口和非final类代理,不能代理static方法

分享到:
评论

相关推荐

    使用Spring的注解方式实现AOP的细节

    本篇文章将深入探讨如何通过Spring的注解方式实现AOP的细节。 首先,我们需要了解AOP的基本概念。AOP的核心是切面(Aspect),它封装了跨越多个对象的行为或责任。切点(Pointcut)定义了哪些方法会被通知(Advice...

    Spring实现AOP的4种方式

    本篇文章将详细探讨Spring实现AOP的四种主要方法:基于代理的方式、基于AspectJ的注解方式、基于XML的AOP配置以及基于Java的AOP配置。 1. 基于代理的实现 Spring的AOP支持两种代理类型:JDK动态代理和CGLIB代理。...

    利用C#实现AOP常见的几种方法详解

    在C#中,实现AOP的方法多种多样,以下将详细介绍几种常见的实现方式。 1. **静态织入**: 静态织入是在编译时完成的,它通过编译器或者编译插件(如PostSharp)在目标类的代码中插入拦截逻辑。这种方式的优点是...

    Spring实现AOP的4种方式 - Java -

    下面我们将详细探讨Spring实现AOP的四种主要方式。 1. **基于注解的AOP** Spring框架自2.5版本开始支持基于注解的AOP,这种方式无需XML配置,更加简洁直观。开发者可以在方法上使用`@Aspect`、`@Before`、`@After`...

    注解方式实现AOP编程

    总结一下,注解方式实现AOP编程主要包括以下几个步骤: 1. 创建一个`@Aspect`注解的类来定义切面。 2. 使用`@Pointcut`定义切点表达式。 3. 使用`@Before`, `@After`, `@AfterReturning`, `@AfterThrowing`, 或 `@...

    spring注解方式实现aop

    通过以上步骤,我们可以使用Spring注解方式实现AOP,将关注点如日志、缓存等与业务逻辑分离,提高代码的可读性和可维护性。在实际项目中,可以灵活运用这些知识来优化代码结构,降低复杂性。希望本教程对理解和应用...

    Spring 基于基于XML配置方式实现AOP

    本篇文章将重点讲解如何通过XML配置方式在Spring中实现AOP。 首先,了解AOP的基本概念是必要的。AOP的核心是切面(Aspect),它封装了多个相关操作,形成了一个关注点。切点(Pointcut)定义了这些操作应用到何处,...

    Asp.net Core 3.1基于AspectCore实现AOP实现事务、缓存拦截器功能

    在net core2.2时,我当时就尝试过用autofac实现aop,但这次我不想用autofac,我用了一个更轻量级的框架,AspectCore。 用起来非常非常的简单,但一开始还是走了一点弯路,主要是网上都是net core3以下的教程,3以下...

    aop的四种实现方式

    **Java 动态代理**是Java标准库提供的另一种实现AOP的方式,主要针对接口。它允许我们创建一个代理类,该类在调用目标接口方法之前和之后执行自定义逻辑。这在处理基于接口的切面时非常有用。 ```java interface ...

    Spring实现AOP的四种方式

    本文将详细介绍Spring实现AOP的四种方式,包括基于代理的经典方式、@AspectJ注解驱动、纯POJO切面以及注入式AspectJ切面。 首先,理解AOP的基本概念: 1. **通知(Advice)**:通知定义了切面在何时执行,Spring支持...

    JavaEE CGLIB字节码增强方式实现AOP编程

    总的来说,JavaEE CGLIB字节码增强方式提供了一种灵活的手段来实现AOP编程,它通过动态生成字节码创建目标类的子类,实现了对目标方法的拦截和增强,从而在不修改原有代码的基础上,增强了代码的功能和可维护性。...

    Spring注解方式实现AOP demo

    本篇将通过注解方式探讨如何在Spring中实现AOP,基于提供的资源,我们可以看到一个实际的Demo项目结构。 首先,我们来看项目的基本结构: 1. `bin`目录:编译后的Java类文件会放在这里。 2. `.settings`目录:包含...

    SpringXML方式实现AOP demo

    标题 "SpringXML方式实现AOP demo" 涉及到的是使用Spring框架通过XML配置来实现面向切面编程(AOP)的知识。面向切面编程是Spring框架的一个核心特性,它允许开发者在不修改原有业务代码的情况下,对系统进行横切...

    Spring实现AOP的四种方式.pdf

    Spring 实现 AOP 的四种方式 Spring 框架提供了四种方式来实现Aspect-Oriented Programming(AOP),分别是经典的基于代理的 AOP、@AspectJ 注解驱动的切面、纯 POJO 切面和注入式 AspectJ 切面。下面将详细介绍这...

    使用Spring的注解方式实现AOP

    在Spring中,注解方式实现AOP主要包括以下几个关键注解: 1. `@Aspect`:这个注解用于定义一个切面类,该类包含了若干个通知(advice)。 2. `@Before`:在目标方法执行前执行的通知,相当于传统的“前置通知”。 3...

    XML方式实现AOP编程

    **XML方式实现AOP编程** 在软件开发中,面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,它旨在提高代码的可重用性和可维护性,通过将关注点分离,使得业务逻辑与横切关注点(如日志、事务...

    android 实现AOP 使用Aspectj Kotlin版Demo.zip

    这个"android 实现AOP 使用Aspect Kotlin版Demo"就是一个实例,展示了如何在Kotlin中利用AspectJ进行AOP编程。 首先,我们要了解AOP的基本概念。面向切面编程的核心在于“切面”和“通知”。切面是关注点的模块化,...

    Spring AOP面向切面三种实现

    本文将详细解析Spring AOP的三种实现方式,帮助你深入理解这一重要概念。 首先,理解AOP的基本概念至关重要。AOP是一种编程范式,它允许开发者定义“切面”,即关注点的模块化,如日志、事务管理等。这些切面可以...

    JavaEE spring自动实现AOP代理

    Spring 提供了两种方式来实现AOP代理:JDK动态代理和CGLIB代理。 1. **JDK动态代理**: - JDK动态代理基于Java的接口实现,适用于目标对象实现了接口的情况。Spring会为这个接口创建一个代理类,代理类在调用真实...

    Spring实现AOP的多种方式 切点函数

    里面包括4个例子:(1)Spring实现AOP方式之一:基于XML配置的Spring AOP (2)Spring实现AOP方式之二:使用注解配置 Spring AOP (3)Spring AOP : AspectJ Pointcut 切点 (4)Spring AOP : Advice 声明 (通知注解)

Global site tag (gtag.js) - Google Analytics