Java通过原始的方式实现AOP【动态代理+反射】

aop的定义

 在不修改源代码的情况下给程序动态添加一些额外的功能

aop的作用

采取横向抽取机制【即动态代理】取代传统的继承机制的重复性代码

aop大致步骤:

  1. 定义代理方法的接口
  2. 定义类实现接口
  3. 写一个Handler实现InovcationHandler接口的invoke方法
  4. 方法内部使用method.invoke(对象,构造参数)
  5. 在invoke上面写一个切面类的反射并且调用对应方法:

        Class clazz = Class.forName("com.....");

        Constructor constructor = clazz.getConstructor(参数对应的类名如(int.class));

        constructor.setAccessible(true);

        Object o = constructor.newInstance(<构造参数赋值>);

        Method method = clazz.getMethod("方法名");

        method.invoke(o,"方法参数");

    6.也可以在代理invoke后执行对应的反射方法。

aop的应用场景:

日志记录、事务管理、权限验证、性能检测

aop使用的基本步骤:

首先是动态代理部分:

[先动态代理后在代理的invoke方法上下添加切面类的反射,然后可以IOC注入对象操作]

​​​​​​1. 定义一个所需要运行实现的方法的接口

package org.example;
public interface TollGateInter {
    public float tollFee();
}

2. 定义一个类,该类实现该接口的方法

package org.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Car implements TollGateInter{
    private float distance;

    public void setDistance(float distance) {
        this.distance = distance;
    }
    @Bean(name="Car")
    public Car Car() {
        return new Car();
    }
    public float tollFee() {
        return (float) (distance*0.5);
    }
}

3. 写一个动态代理实现invocationHandler接口的invoke方法 

public class TestHandler implements InvocationHandler {
    private Object object;
    public TestHandler(Truck truck){
        object = truck;
    }
    public TestHandler(Bus bus){
        object = bus;
    }
    public TestHandler(Car car){
        object = car;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // System.out.println("代理开始:~~~~");
        // Class clazz = Class.forName("org.example.TollAspects");
        // Constructor constructor = clazz.getConstructor();
        // Object o = constructor.newInstance();
        // Method method1 = clazz.getMethod("welcome",int.class);
        // method1.invoke(o,2);

        Object result = method.invoke(object,args);//arg为参数,object为要代理的对象

        // Method method2 = clazz.getMethod("nextWelcome");
        // method2.invoke(o);
        // System.out.println("代理结束:~~~~");
        return result;
    }
}

4. 在主函数中实例化动态代理对象加入相关参数实现动态代理该方法 

InvocationHandler invocationHandler = new TestHandler(new Car());
//可以在构造方法内放参数
TollGateInter car1 = (TollGateInter) Proxy.newProxyInstance(
    Main.class.getClassLoader(),new Class[]{
        TollGateInter.class
    },invocationHandler);

 其次是通过反射的方式在代理前后通过反射添加操作:

1. 定义一个切面类:

package org.example;
public class TollAspects {
    public void welcome(int a){
        System.out.println("欢迎光临收费站!"+a);
    }
    public void nextWelcome(){
        System.out.println("欢迎下次再来!");
    }
}

2. 在代理的invoke方法前后添加反射操作实现切面类的调用:

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("代理开始:~~~~");
    Class clazz = Class.forName("org.example.TollAspects");
    Constructor constructor = clazz.getConstructor();
    Object o = constructor.newInstance();
    Method method1 = clazz.getMethod("welcome",int.class);
    method1.invoke(o,2);
    //-----------------代理前执行操作----------------
    Object result = method.invoke(object,args);//--------------
    //-----------------代理后进行操作---------------
    Method method2 = clazz.getMethod("nextWelcome");
    method2.invoke(o);
    System.out.println("代理结束:~~~~");
    return result;
}

作业题:

速公路收费系统针对不同的车辆收费也不一样,例如可能有如下的收费标准:七座以下的小汽车按里程收费,每公里0.5元,大巴车按可载乘员人数和里程收费,大于7人小于20人每公里1元,20人以上每公里1.2元。货车按载重量和里程收费,每吨每公里1元。每一种类型的车都通过编写一个车辆类来实现,简单起见,每种类型的车都有一个方法tollFee ,用来计算运费。
由于车辆类型和路费计算方法存在变数,收费站功能也存在今后进一步扩展的可能,要求设计并开发一个带有IOC和AOP功能的高速公路收费系统框架。
要求:1、开发一个收费程序TollGate类,该类至少具有一个收费charge功能,可以通过键盘输入的汽车类型和里程计算并输出过路费金额。车辆的类型可以是任意用户输入的类型,可通过一个可配置的IOC容器获取相关的车辆对象。对于新的车辆类型仅需要修改配置文件和编写相应的车辆类即可。
2、提供一个切面程序类,供今后进行功能扩展。系统可以通过一个可配置的AOP的方式对收费过程charge进行扩展。例如:可在收费前打印输出“欢迎光临xxx收费站,行驶里程数为xxxxx”,或在收费后打印输出文字“谢谢,祝旅途顺利!”。新功能扩展通过修改配置文件和切面程序类即可完成。

实现:

主函数:TollGate.calss

package org.example;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Scanner;

public class TollGate {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        InvocationHandler invocationHandler;
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
            "applicationContext.xml"
        );
        while (true){
            System.out.println("请输入车辆类型:(0:小汽车/1:大巴车/2:货车)");
            int id = scanner.nextInt();
            if(id == 0){
                Car car = (Car) context.getBean("Car");
                System.out.println("输入里程数:");
                float dis = scanner.nextFloat();
                car.setDistance(dis);
                invocationHandler = new TestHandler(car);
            } else if (id == 1) {
                scanner.nextLine();
                Bus bus = (Bus) context.getBean("Bus");
                System.out.println("输入人数和里程数:");
                String s = scanner.nextLine();
                String[] s1 = s.split(" ");
                bus.setNum(Integer.parseInt(s1[0]));
                bus.setDistance(Float.parseFloat(s1[1]));
                invocationHandler = new TestHandler(bus);
            }else {
                scanner.nextLine();
                Truck truck = (Truck) context.getBean("Truck");
                System.out.println("输入重量和里程数:");
                String s = scanner.nextLine();
                String[] s1 = s.split(" ");
                truck.setWeight(Float.parseFloat(s1[0]));
                truck.setDistance(Float.parseFloat(s1[1]));
                invocationHandler = new TestHandler(truck);
            }
            TollGateInter car1 = (TollGateInter) Proxy.newProxyInstance(
                Main.class.getClassLoader(),
                new Class[]{TollGateInter.class},
                invocationHandler
            );
            car1.tollFee();
        }
    }
}

代理:TestHandler.class 

package org.example;

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

public class TestHandler implements InvocationHandler {
    private Object object;
    public TestHandler(Truck truck){
        object = truck;
    }
    public TestHandler(Bus bus){
        object = bus;
    }
    public TestHandler(Car car){
        object = car;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Class clazz = Class.forName("org.example.TollAspects");
        Object o = clazz.newInstance();
        Method method1 = clazz.getMethod("welcome",int.class);
        method1.invoke(o,2);

        Object result = method.invoke(object,args);

        Method method2 = clazz.getMethod("nextWelcome");
        method2.invoke(o);
        return result;
    }
}

切面类:TollAspects.class 

package org.example;
public class TollAspects {
    public void welcome(int a){
        System.out.println("欢迎光临收费站!"+a);
    }
    public void nextWelcome(){
        System.out.println("欢迎下次再来!");
    }
}

Bean类:Bus.class【只写了一个】 

package org.example;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Bus  implements TollGateInter{
    private int num;
    private float distance;

    public void setNum(int num) {
        this.num = num;
    }

    public void setDistance(float distance) {
        this.distance = distance;
    }
    @Bean(name = "Bus")
    public Bus Bus() {
        return new Bus();
    }
    public float tollFee(){
        if(num>7 && num <20){
            System.out.println("大巴车费用为:"+ distance);
            return distance;
        }else {
            System.out.println("大巴车费用为:"+ distance*1.2);
            return (float) (distance*1.2);
        }
    }

}

bean.xml 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  http://www.springframework.org/schema/mvc
  http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
  <context:component-scan base-package="org.example"/>
  <aop:aspectj-autoproxy/>
</beans>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值