自己动手写aop(一)

博主对之前写的AOP代码进行研究,通过创建接口、实现类等操作,分析代码运行结果,发现AopHandle生成新实现类。探讨如何指定特定方法进行代理,最终通过调用原对象方法及修改AopHandle实现部分方法代理,实现面向切面效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

水平有限,静待各位大佬提出的宝贵的建议。

1.前几天写的aop又看不懂了。再次研究看看重拾记忆。

2.这里创建一个接口,SayHello 

public interface SayHello {
    String say(String name);
}

3.接口实现类 ManSayHello 

public class ManSayHello implements SayHello{
    private String name ;
    @Override
    public String say(String name) {
        System.out.println(name+" say : Hello world!");
        return name+" is the speaker's name";
    }
}

4.AOPHandle 


/**
 * 此处用到静态代理模式  Object obj 为真实角色(被代理角色);AOPHandle 创建的对象为代理角色
 */
public class AOPHandle implements InvocationHandler {
    private Object obj;
    AOPHandle(Object obj){
        this.obj = obj;
    }

    @Override
    /**
     *
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法返回值
        System.out.println("前置代理");
        //反射调用方法
        Object ret=method.invoke(obj, args);
        //声明结束
        System.out.println("后置代理");
        //返回反射调用方法的返回值
        return ret;
    }
}

5.调用此say方法时 运行

package com.iflytek.edu;

import com.iflytek.edu.aop.HelloWorldImpl;
import org.springframework.cglib.proxy.Proxy;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author (2084318355@qq.com)
 * @Description
 * @Time Created on 2019/3/7 10:24.
 */
public class Main {
    public static void main(String[] args) throws Throwable {
        ManSayHello manSayHello = new ManSayHello();
        AOPHandle handle = new AOPHandle(manSayHello);
        //下面这段代码实际上生成了一个新的接口实现类的方法??
        SayHello sayHello = (SayHello) Proxy.newProxyInstance(SayHello.class.getClassLoader(), new Class[] { SayHello.class }, handle);
        String rs = sayHello.say("Linda");
        System.out.print(rs);
    }
}

6.观察上述代码,在执行 sayHello.say("Linda"); 这段代码时,结果如下

与我们所认识的manSayHello 这个对象的say方法已经产生了差别,原因在于SayHello这个接口在

SayHello sayHello = (SayHello) Proxy.newProxyInstance(SayHello.class.getClassLoader(), new Class[] { SayHello.class }, handle);

这段代码运行完成之后产生了一个新的方法。仔细思考,是只产生一个新的方法,还是为所有方法都产生了新的方法?

7.做个测试,修改SayHello接口,让他多一些新的方法,再让接口实现类实现这些方法。

SayHello

public interface SayHello {
    String say(String name);
    void hello();
    void hi();
}

ManSayHello 

public class ManSayHello implements SayHello{
    private String name ;
    @Override
    public String say(String name) {
        System.out.println(name+" say : Hello world!");
        return name+" is the speaker's name";
    }

    @Override
    public void hello() {
        System.out.println("hello");
    }
    @Override
    public void hi() {
        System.out.println("hi");
    }
}

Main 

package com.iflytek.edu;

import com.iflytek.edu.aop.HelloWorldImpl;
import org.springframework.cglib.proxy.Proxy;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author 2084318355@qq.com
 * @Description
 * @Time Created on 2019/3/7 10:24.
 */
public class Main {
    public static void main(String[] args) throws Throwable {
        ManSayHello manSayHello = new ManSayHello();
        AOPHandle handle = new AOPHandle(manSayHello);
        //下面这段代码实际上生成了一个新的接口实现类的方法??
        SayHello sayHello = (SayHello) Proxy.newProxyInstance(SayHello.class.getClassLoader(), new Class[] { SayHello.class }, handle);
        String rs = sayHello.say("Linda");
        System.out.println(rs);
        sayHello.hello();
        sayHello.hi();
    }
}

 

8.结果如下

结果说明刚才的AopHandle生成了一个新的实现类,这个类的所有方法都是由 前置代理+manSayHello的实现方法+后置代理 这三个东西组合到一起的。而在实际当中不可能是为每个方法都 进行这样的操作,因此如何指定特定方法呢?。

9.突然觉得自己傻出新高度!

只要后面调用的对象不是代理生成的新类就行了呀!用之前的对象manSayHello调用方法不就行了吗,如下 hello,hi都是用之前的对象的方法,因此不会出现三个前置代理和后置代理!

至此,完成了调用特定方法时产生的效果。

11.但是这样看不出来面向切面的感觉,后面加以修改:

主要改了AopHandle,对其中的方法名字做检查,让某些方法实现代理(方法重写)。

import org.springframework.cglib.proxy.InvocationHandler;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 此处用到静态代理模式  Object obj 为真实角色(被代理角色);AOPHandle 创建的对象为代理角色
 */
public class AOPHandle implements InvocationHandler {
    private Object obj;
    AOPHandle(Object obj,List<String> methodName){
        this.obj = obj;
        this.setMethodName(methodName);
    }
    AOPHandle(Object obj){
        this.obj = obj;
        this.setMethodName(methodName);
    }
    List<String> methodName;

    public List<String> getMethodName() {
        return methodName;
    }

    public void setMethodName(List<String> methodName) {
        this.methodName = methodName;
    }

    private Object executeProxy(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
        //方法返回值
        System.out.println("前置代理");
        //反射调用方法
        Object ret = method.invoke(obj, args);
        //声明结束
        System.out.println("后置代理");
        //返回反射调用方法的返回值
        return ret;
    }
    @Override
    /**
     *
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //methodName里面定义所有可以切入的方法

        if(methodName!=null&&methodName.size()>0){
            int i=0;
            while (i < methodName.size()){
                if(method.getName().equals(methodName.get(i++))){
                    return executeProxy(proxy,method,args);
                }
            }
            Object ret=method.invoke(obj, args);
            return ret;
        }else {
           return executeProxy(proxy,method,args); //如果methodName为空 则给所有方法代理
        }
    }
}

再运行下面的

ManSayHello manSayHello = new ManSayHello();
List<String> methodName = new ArrayList<String>();
methodName.add("say");//此处定义需要被切入的方法

//下面这段代码实际上生成了一个新的接口实现类的所有方法
SayHello sayHello = (SayHello) Proxy.newProxyInstance(SayHello.class.getClassLoader(), new Class[] { SayHello.class }, new AOPHandle(manSayHello,methodName));
String rs = sayHello.say("Linda");
System.out.println(rs);
sayHello.hello();
sayHello.hi();

完美啊!

现在同一个sayHello对象,对应不同的方法中某些方法被代理了,有些没有被代理!

水平有限,静待各位大佬提出的宝贵的建议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值