hutool学习第一天-aop

普通实现方式

1. JDK 动态代理

JDK 动态代理是基于 Java 反射机制的一种代理方式,它允许在运行时动态创建实现了某些接口的代理对象。它的主要特点是:

  • 要求:被代理的类必须实现一个或多个接口。
  • 代理类:由 java.lang.reflect.Proxy 类动态生成。
  • 核心接口InvocationHandler
详细实现步骤:
  1. 定义接口:创建一个接口,规定要代理的方法。

    public interface HelloService {
        void sayHello();
    }
    
  2. 实现接口:创建一个实现接口的具体类。

    public class HelloServiceImpl implements HelloService {
        @Override
        public void sayHello() {
            System.out.println("Hello, world!");
        }
    }
    
  3. 创建 InvocationHandler:实现 InvocationHandler 接口,以便在方法调用时插入自定义逻辑。

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class MyInvocationHandler implements InvocationHandler {
        private Object target;
    
        public MyInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Before method: " + method.getName());
            Object result = method.invoke(target, args);
            System.out.println("After method: " + method.getName());
            return result;
        }
    }
    
  4. 生成代理对象:使用 Proxy.newProxyInstance 创建代理对象。

    import java.lang.reflect.Proxy;
    
    public class JDKProxyDemo {
        public static void main(String[] args) {
            HelloService target = new HelloServiceImpl();
            HelloService proxy = (HelloService) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new MyInvocationHandler(target)
            );
            proxy.sayHello();
        }
    }
    

2. Cglib 动态代理

Cglib 代理通过继承被代理的类来创建代理对象,因此不需要被代理的类实现接口。Cglib 主要用于类级别的代理。

详细实现步骤:
  1. 添加 Cglib 依赖:首先,需要在项目中引入 Cglib 依赖(如果使用 Maven)。

    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version>
    </dependency>
    
  2. 定义普通类:创建一个需要被代理的普通类。

    public class HelloService {
        public void sayHello() {
            System.out.println("Hello, world!");
        }
    }
    
  3. 实现 MethodInterceptor:实现 MethodInterceptor 接口以定义拦截逻辑。

    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class MyMethodInterceptor implements MethodInterceptor {
        private Object target;
    
        public MyMethodInterceptor(Object target) {
            this.target = target;
        }
    
        @Override
        public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("Before method: " + method.getName());
            Object result = proxy.invoke(target, args);
            System.out.println("After method: " + method.getName());
            return result;
        }
    }
    
  4. 创建代理对象:使用 Enhancer 来创建代理对象。

    import net.sf.cglib.proxy.Enhancer;
    
    public class CglibProxyDemo {
        public static void main(String[] args) {
            HelloService target = new HelloService();
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(new MyMethodInterceptor(target));
            HelloService proxy = (HelloService) enhancer.create();
            proxy.sayHello();
        }
    }
    

3. Spring AOP 的 Cglib 代理

Spring AOP 可以通过 Cglib 代理来实现对类的增强。Spring AOP 在底层使用了 Cglib 来生成代理类,尤其在被代理的类没有实现接口时。

详细实现步骤:
  1. 添加 Spring AOP 依赖:在项目中引入 Spring AOP 相关的依赖(如果使用 Maven)。

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.3.24</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.24</version>
    </dependency>
    
  2. 定义服务类:创建一个使用 Spring 注解的服务类。

    import org.springframework.stereotype.Service;
    
    @Service
    public class HelloService {
        public void sayHello() {
            System.out.println("Hello, world!");
        }
    }
    
  3. 创建切面类:使用 @Aspect 注解定义切面,并实现切面逻辑。

    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class LoggingAspect {
        @Around("execution(* HelloService.sayHello(..))")
        public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("Before method: " + joinPoint.getSignature().getName());
            Object result = joinPoint.proceed();
            System.out.println("After method: " + joinPoint.getSignature().getName());
            return result;
        }
    }
    
  4. 配置 Spring AOP:配置 Spring 来启用 AOP 功能。

    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @Configuration
    @EnableAspectJAutoProxy
    @ComponentScan(basePackages = "your.package")
    public class AppConfig {
    }
    
  5. 主程序:使用 Spring 上下文来获取服务类的代理对象。

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class SpringAopDemo {
        public static void main(String[] args) {
            ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            HelloService helloService = context.getBean(HelloService.class);
            helloService.sayHello();
        }
    }
    

总结

  • JDK 动态代理:适用于代理实现了接口的类,使用 java.lang.reflect.Proxy 生成。
  • Cglib 代理:适用于代理没有实现接口的类,通过继承生成代理类。
  • Spring AOP Cglib 代理:Spring 使用 Cglib 实现对类的增强,支持注解方式的切面编程。

hutool工具包实现方式

引入hutool工具包

	<dependency>
	       <groupId>cn.hutool</groupId>
	       <artifactId>hutool-all</artifactId>
	       <version>5.3.6</version>
	</dependency>

ProxyFactory生成代理对象

  • CglibProxyFactory 基于Cglib的切面代理工厂
  • JdkProxyFactory JDK实现的切面代理
  • SpringCglibProxyFactory 基于Spring-cglib的切面代理工厂
  1. createProxy

createProxy默认使用Cglib 动态代理

在这里插入图片描述

  • 如何使用
public void test(){
        Cat proxy = ProxyFactory.createProxy(new Cat(), SimpleAspect.class);
        proxy.eat();
    }

new Cat()为目标对象,SimpleAspect.class为切面对象,hutool提供了两个切面对象类

  • SimpleAspect类,是基本类,所有自定义开发的切面对象都需要集成该类
  • TimeIntervalAspect类,为通过日志打印方法的执行时间的切面
public void TimeIntervalAspectTest(){
        Cat proxy = ProxyFactory.createProxy(new Cat(), TimeIntervalAspect.class);
        proxy.eat();
    }

在这里插入图片描述
2. proxy

如果不想使用默认的的Cglib 动态代理,可以使用该方法自定义创建

	 @Test
    public void ProxyTest(){
        ProxyFactory proxyFactory = new ProxyFactory() {
            @Override
            public <T> T proxy(T target, Aspect aspect) {
                /**
                 * 1、CglibProxyFactory 基于Cglib的切面代理工厂
                 * 2、JdkProxyFactory JDK实现的切面代理
                 * 3、SpringCglibProxyFactory 基于Spring-cglib的切面代理工厂
                 */
                return JdkProxyFactory.createProxy(target, aspect);
            }
        };
        Cat proxy = ProxyFactory.createProxy(new Cat(), TimeIntervalAspect.class);
        proxy.eat();
    }

如何创建自己的切面对象类

  1. 继承SimpleAspect简单切面类

简单切面类,不做任何操作 可以继承此类实现自己需要的方法即可

	public class MyAopAspect extends SimpleAspect {
    @Override
    public boolean before(Object target, Method method, Object[] args) {
        System.out.println("before");
        return true;
    }

    @Override
    public boolean after(Object target, Method method, Object[] args, Object returnVal) {
        System.out.println("after");
        return true;
    }

    @Override
    public boolean afterException(Object target, Method method, Object[] args, Throwable e) {
        System.out.println("afterException");
        return true;
    }
}
	@Test
    public void testMyAopAspect(){
        Cat proxy = ProxyFactory.createProxy(new Cat(), MyAopAspect.class);
        proxy.eat();
    }
  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孑疋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值