AOP+代理(2.24)

一、AOP

1.AOP概念:面向切面编程

image-20260128200054868

2.切点:方法

连接点:被切面选中的方法

切面类:补强的方法(可变的部分),可以为多个连接点进行补强

  • 前置-->前置通知 Advice
  • 后置-->后置通知

3.Aop的用处:

业务日志:后置通知

统一异常处理:controller层try catch改为植入的方式

事务

鉴权

二、代理

1.概念:

image-20260224211150387

代理 = 代理对象包裹目标对象 + 对目标方法的任意增强(可前置/后置/环绕/异常/替换)

2.分类:

静态代理:编译期 增强

动态代理:运行期 增强

  • jdk 动态代理接口动态增强 不频繁
  • cglib 动态代理动态增强 频繁

静态代理:

image-20260224214421846

cglib动态代理:

image-20260224215245833

三、代理实战:

1.静态代理:

项目结构:

image-20260224233259779

Restaurant接口:

public interface Restaurant {
    void eatMeet(String  meet);
    void eatFish(String fish);    
}

PeaceRestaurant实现类:

public class PeaceRestaurant implements  Restaurant{

    @Override
    public void eatMeet(String meet) {
        System.out.println(meet + "9999 一份");
    }
    
    @Override
    public void eatFish(String fish) {
        System.out.println(fish + "666 一份");
    }
}

ProxyRestaurant代理类:

public class ProxyRestaurant implements  Restaurant{

    private Restaurant restaurant;

    public ProxyRestaurant(Restaurant restaurant){
        this.restaurant = restaurant;
    }
    
    @Override
    public void eatMeet(String meet) {
        System.out.println("开始点餐");
        restaurant.eatMeet(meet);
        System.out.println("送你500代金券");
    }
    
    @Override
    public void eatFish(String fish) {
        System.out.println("本地鱼,打八折");
        restaurant.eatFish(fish);

    }
}

Main:

public class Main {
    public static void main(String[] args) {
        Restaurant restaurant = new PeaceRestaurant();//多态
        restaurant.eatFish("鳕鱼");
        System.out.println("--------使用代理---------");
        ProxyRestaurant proxy = new ProxyRestaurant(restaurant);
        proxy.eatFish("金龙鱼");

    }
}

执行结果:

鳕鱼666 一份
--------使用代理---------
本地鱼,打八折
金龙鱼666 一份

2.(1)jdk动态代理:

项目结构:

image-20260224234814682

Restaurant接口:

public interface Restaurant {

    void eatMeet(String  meet);
    void eatFish(String fish);
}

PeaceRestaurant实现类:

public class PeaceRestaurant implements Restaurant {

    @Override
    public void eatMeet(String meet) {
        System.out.println(meet + "9999 一份");
    }

    @Override
    public void eatFish(String fish) {
        System.out.println(fish + "666 一份");

    }
}

ProxyRestaurantJdk代理类:

public class ProxyRestaurantJdk implements InvocationHandler {

    private Object target;

    public ProxyRestaurantJdk(Object target){
        this.target = target;

    }
    //代理方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(proxy.getClass());
        System.out.println("吃饭前洗手");
        //调用目标方法
        Object ret = method.invoke(target, args);
        System.out.println("吃饭后洗手");
        return ret;
    }
}

Main:

public class Main {
    public static void main(String[] args) {
		//PeaceRestautant 目标对象
        Restaurant restaurant = new PeaceRestaurant();
        restaurant.eatFish("黄花鱼");
        System.out.println("--------使用代理---------");
		//增强后的代理对象
        ProxyRestaurantJdk proxyRestautantJdk = new ProxyRestaurantJdk(restaurant);
        //动态生成的目标代理对象, 类的所有方法都被代理
        Restaurant restaurant1 = (Restaurant) Proxy.newProxyInstance(
               restautant.getClass().getClassLoader(), //相同的类的加载器
               restautant.getClass().getInterfaces(), //生成的代理对象,具有相同的接口数组
               proxyRestautantJdk //增强的代码逻辑
        );
        restaurant1.eatFish("金龙鱼");
        restaurant1.eatMeet("牛排");

    }
}

执行结果:

黄花鱼666 一份
--------使用代理---------
class jdk.proxy1.$Proxy0
吃饭前洗手
金龙鱼666 一份
吃饭后洗手
class jdk.proxy1.$Proxy0
吃饭前洗手
牛排9999 一份
吃饭后洗手

(2)jdk动态代理优化:

main:

public class Main {
    public static void main(String[] args) {

        Restaurant restaurant = new PeaceRestaurant();
        restaurant.eatFish("黄花鱼");
        System.out.println("--------使用代理---------");

        //ProxyRestaurantJdk proxyRestautantJdk = new ProxyRestaurantJdk(restaurant);
        //动态生成的目标代理对象
        Restaurant restaurant1 = (Restaurant) Proxy.newProxyInstance(
                PeaceRestaurant.class.getClassLoader(), //相同的类的加载器
                PeaceRestaurant.class.getInterfaces(), //生成的代理对象,具有相同的接口数组
                new ProxyRestaurantJdk(restaurant) //增强的代码逻辑
        );
        restaurant1.eatFish("金龙鱼");
        restaurant1.eatMeet("牛排");

    }
}

执行结果:

黄花鱼666 一份
--------使用代理---------
class jdk.proxy1.$Proxy0
吃饭前洗手
金龙鱼666 一份
吃饭后洗手
class jdk.proxy1.$Proxy0
吃饭前洗手
牛排9999 一份
吃饭后洗手

3.cglib动态代理(了解):

项目结构:

image-20260225000852676

PeaceRestaurant类:

public class PeaceRestaurant {

    public void eatMeet(String meet) {
        System.out.println(meet + "9999 一份");
    }

    public void eatFish(String fish) {
        System.out.println(fish + "666 一份");
    }
}

ProxyRestaurantCglib代理类:

public class ProxyRestaurantCglib implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("cglib代理执行前" + method.getName());
        //调用目标对象的方法
        Object o = proxy.invokeSuper(obj,args);
        System.out.println("cglib代理执行后" + method.getName());
        return o;
    }
}

Main:

public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();

        enhancer.setSuperclass(PeaceRestaurant.class);
        enhancer.setCallback(new ProxyRestaurantCglib());

        PeaceRestaurant restaurant = (PeaceRestaurant)enhancer.create();
        restaurant.eatFish("鱼香肉丝");
        restaurant.eatMeet("红烧肉");

    }
}

执行结果:

cglib代理执行前eatFish
鱼香肉丝666 一份
cglib代理执行后eatFish
cglib代理执行前eatMeet
红烧肉9999 一份
cglib代理执行后eatMeet

四、Aop使用:

controller.CarController:

@RestController
@RequestMapping("/car")
public class CarController {

    @Autowired
    private CarService carService;

    @GetMapping("/all")
    public List<Car> listGet() {
        List<Car> carList = null;
        try{
            carList = carService.findAll();
            System.out.println("carList:"+carList);
        }catch (Exception e) {
           throw new RuntimeException(e);
        }
        return carList;
    }

}

aop.TimeAspect:

@Component
@Aspect //当前类是个切面
public class TimeAspect {
    //1 切点逻辑 哪些类的哪些方法
    //execution([访问修饰符] 返回值类型 包名.类名.方法名(参数类型) [异常])
    //      任意返回值类型  包名.类名.方法名
    @Pointcut("execution(* cn.wolfcode.controller.*.*(..))")
    public void pointcut(){}

    //2 通知方法 Around 表示通知方式
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = pjp.proceed(); //目标方法调用
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end-start) + "ms");
        return result;
    }
}

BoosApplicationTests:

@SpringBootTest
class BoosApplicationTests {

    @Autowired
    private CarController carController;

    @Autowired
    private DepartmentController departmentController;

    @Test
    void contextLoads() {
        List<Car> carList = carController.listGet();

        departmentController.listGet(new HashMap<>());
    }

}

执行结果:

carList:[Car(id=1, name=Tesla Model 3, color=红色), Car(id=2, name=BMW 5 Series, color=黑色), Car(id=3, name=Toyota Camry, color=白色), Car(id=4, name=Audi A4, color=银色)]
耗时:237ms
耗时:47ms
posted on 2026-02-25 00:44  冬冬咚  阅读(12)  评论(0)    收藏  举报