`

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方法

分享到:
评论

相关推荐

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

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

    Spring实现AOP的四种方式

    配置可以通过xml文件来进行,大概有四种方式: 1. 配置ProxyFactoryBean,显式地设置advisors, advice, target等(基于代理的AOP ) 2. 配置AutoProxyCreator,这种方式下,还是如以前一样使用定义的bean,但是从...

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

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

    Spring  AOP实现方法大全

    在Spring1.2或之前的版本中,实现AOP的传统方式就是通过实现Spring的AOP API来定义Advice,并设置代理对象。Spring根据Adivce加入到业务流程的时机的不同,提供了四种不同的Advice:Before Advice、After Advice、...

    AOP方式实现的redis分布式锁

    2、基于AOP方式实现。 3、只需要在方法上声明@DistributedLock(可以是controller的方法也可以是service的公共方法)即可实现锁功能。 4、支持在@DistributedLock上动态传参,减少锁的颗粒度。

    Spring aop 之 静态代理 动态代理 Aspectj aop-config 等实现方式

    主要对Spring AOP的相关概念和简单的静态代理、动态代理以及常见的几种AOP配置方式做总结学习。主要包括:1. AOP的常见概念 2. 静态代理 3. jdk动态代理 4. Aspectj and Aspectjweaver 5. **aop-config** 6. CGLIB ...

    spring aop 实现源代码--xml and annotation(带lib包)

    在Spring1.2或之前的版本中,实现AOP的传统方式就是通过实现Spring的AOP API来定义Advice,并设置代理对象。Spring根据Adivce加入到业务流程的时机的不同,提供了四种不同的Advice:Before Advice、After Advice、...

    代理设计模式:静态代理和动态代理的理解、实现与区别(优缺点)与SpringAOP的3种配置方式案例工程代码

    此资源为文章中《代理设计模式:静态代理和动态代理的理解、实现与区别(优缺点)》与《 AOP动态代理声明式的3种配置方式过程与区别》的案例代码,可下载参考学习。

    使用Spring AOP对异常进行统一处理

    3.处理日志时,需要在每一个try-catch块包含一些处理代码,有时候异常处理的代码比正常执行代码还多,污染正常执行代码。 4.同样类型异常有不同的处理方式,使最终的处理变得复杂。 5.接口抛出异常,破坏封装,打破...

    开发者突击·精通AOP整合应用开发 源码

    Spring AOP:以loC为基础讲解Spring下的AOP开发,讲解了3种AOP的开发方式,即使用@Aspect注释符、基于Schema的配置的开发方式和Spring API的开发方式,最后在实际的Java EE项目中实现5种Spring AOP功能(日志记录器...

    Spring AOP实验

    3、了解Spring中两种动态代理方式的区别; 4、掌握基于XML和注解的AspectJ开发。 二、 实验内容 1、按图所示的类图结构,设计接口及其实现类,并完成另外两附加要求:(1)日志功能:在程序执行期间追踪正在发生的...

    AOP的动态代理proxy

    1. 首先完成一个接口的创建(里面有真正的想要实现的方法): public interface UserDAO{ public void add (); //想要实现的方法 } 2. 写一个真实的主题类实现...3. 写一个动态的代理类实现InvocationHandler接口:

    实验2 Spring AOP源码

    一:实验目的 1、 理解Spring AOP原理和基本概念; 2、掌握基于XML/注解方式的AOP编程; 二:实验内容 1、 定义交易接口: public interface ...2、 基于XML实现AOP,使得账户余额变动前后进行信息提示; 3、基

    spring-redis-aop:基于aop方式添加redis缓存

    此项目是实现以aop的形式,以annotion方式在实现方法上添加redis缓存 注意: 1.如果用maven打成jar包引入,只需修改一下配置问题 2.也可将代码copy到您的项目中。但要修改一些代码和配置文件 3.对象要实现...

    springboot2+两种方式:(读写分离、动态DataSource、事务懒处理)+sharding-jdbc.zip

    (3)、非注解方式,业务代码侵入基本为零 (4)、懒事务处理方式,service层使用@Transactional注解的方法或者类只能走默认库(写库) (5)、AOP根据Dao层的方法名来判断读写库的切换,超出判断规则的只能走默认...

    SpringAOP使用介绍,从前世到今生

    SpringAOP发展到现在出现的全部3种配置方式。由于Spring强大的向后兼容性,实际代码中往往会出现很多配置混杂的情况,而且居然还能工作,本文希望帮助大家理清楚这些知识。我们先来把它们的概念和关系说说清楚。AOP...

    SpringBoot 注册自己的Servlet(三种方式)(源代码)

    主体框架基于spring,而spring除了Ioc(依赖注入)、Aop(切面)外,其它与http相关的东西都是基于Servlet和Filter的,而Servlet、Filter是servlet容器Jetty按照j2ee标准做了具体实现。目前使用Spring的,更多是在...

    Spring Boot集成Druid实现多数据源的两种方式

    1、集成com.baomidou的方式,引入dynamic-datasource...2、原生的方式,基于AOP手动实现多数据源; 3、项目代码完整,包含注释,能启动测试; 博客地址:https://blog.csdn.net/u011974797/article/details/130109195

Global site tag (gtag.js) - Google Analytics