spring切片是如何实现的

不及物动词 其他 15

回复

共3条回复 我来回复
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    Spring切片(AOP)是通过使用动态代理实现的。Spring框架提供了两种实现动态代理的方式:JDK 动态代理和 CGLIB 动态代理。

    1. JDK 动态代理:
      JDK 动态代理是通过 java.lang.reflect 包提供的 Proxy 类和 InvocationHandler 接口实现的。在运行时,通过 Proxy 类的静态方法 newProxyInstance() 创建代理对象,并传入目标对象和实现 InvocationHandler 接口的类。代理对象会调用 InvocationHandler 的 invoke() 方法,在该方法中可以加入切面逻辑。JDK 动态代理只能对实现了接口的类进行代理,即目标对象必须实现代理接口。

    示例代码:

    public interface UserService {
        void addUser();
    }
    
    public class UserServiceImpl implements UserService {
        public void addUser() {
            System.out.println("Add user");
        }
    }
    
    public class UserServiceProxy implements InvocationHandler {
        private Object target;
    
        public Object bind(Object target) {
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 添加切面逻辑
            System.out.println("Before method");
            Object result = method.invoke(target, args);
            System.out.println("After method");
            return result;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            UserService userService = new UserServiceImpl();
            UserService proxy = (UserService) new UserServiceProxy().bind(userService);
            proxy.addUser();
        }
    }
    
    1. CGLIB 动态代理:
      CGLIB(Code Generation Library)动态代理是通过在运行时生成目标类的子类来实现的。CGLIB 是基于底层的字节码操作库 ASM 进行代码生成。与 JDK 动态代理不同,CGLIB 动态代理可以代理没有实现接口的类。

    示例代码:

    public class UserService {
        public void addUser() {
            System.out.println("Add user");
        }
    }
    
    public class UserServiceInterceptor implements MethodInterceptor {
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            // 添加切面逻辑
            System.out.println("Before method");
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("After method");
            return result;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(UserService.class);
            enhancer.setCallback(new UserServiceInterceptor());
            UserService userService = (UserService) enhancer.create();
            userService.addUser();
        }
    }
    

    总结:
    Spring切片通过使用动态代理实现切面逻辑的添加。JDK 动态代理只能对实现了接口的类进行代理,而CGLIB 动态代理可以代理没有实现接口的类。根据实际业务需求,选择适合的方式实现切片。

    1年前 0条评论
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    Spring的切片是通过AspectJ框架实现的。AspectJ是一个用于在Java代码中实现面向切面编程的框架。它允许开发人员在代码中定义切面,并且可以将这些切面应用于特定的方法、类或对象上。

    下面是Spring切片实现的一些关键点:

    1. 切面定义:在Spring中,切面被定义为一个使用@Aspect注解的普通类。通过在该类中定义一些通知(advice),可以在应用程序中的不同点(例如方法的进入、退出或抛出异常)上插入切面逻辑。

    2. 通知类型:Spring支持五种不同类型的通知,分别是前置通知(Before)、后置通知(After)、返回通知(AfterReturning)、异常通知(AfterThrowing)和环绕通知(Around)。开发人员可以根据需要选择适当的通知类型。

    3. 切点:切点是指在应用程序中选定一个或多个连接点(join points),这些连接点是切面将被应用的地方。切点可以通过使用表达式来定义,例如基于方法名、包名和注解等进行选择。

    4. 连接点:连接点是程序执行过程中能够被注入切面逻辑的特定位置。在Spring中,连接点可以是方法调用、方法入口、方法退出或抛出异常等。开发人员可以选择要拦截的连接点,并将切面逻辑应用于这些连接点。

    5. 织入:织入是指将切面逻辑与应用程序的目标对象(target object)进行合并的过程。Spring提供了两种织入方式,一种是编译时织入(Compile-time Weaving),另一种是运行时织入(Runtime Weaving)。编译时织入是在编译代码时将切面逻辑织入目标对象,而运行时织入是在运行时通过使用代理对象或字节码操作来织入切面逻辑。

    综上所述,Spring的切片是通过AspectJ框架实现的。开发人员可以使用Spring提供的注解和配置来定义切面,并将切面逻辑应用于应用程序中的特定连接点。这种面向切面的编程使得开发人员能够将横切关注点(cross-cutting concerns)与核心业务逻辑进行解耦,并提供了一种灵活、可重用的方式来处理共享的横切关注点。

    1年前 0条评论
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    Spring切面(Aspect)是Spring AOP的一种实现方式,通过使用切面,我们可以将特定的逻辑(切点)与业务逻辑(连接点)解耦,并在相应的连接点上执行这些逻辑。Spring切面是基于代理技术实现的,通过动态生成代理对象来实现切面的功能。

    下面是Spring切面实现的具体步骤:

    1. 定义切面类:切面类是一个普通的Java类,通过在该类上添加@Aspect注解,告诉Spring该类是一个切面类。切面类中定义了一些切点和通知方法来实现具体的切面逻辑。
    @Aspect
    public class MyAspect {
        // 定义切点
        @Pointcut("execution(* com.example.service.*.*(..))")
        public void myPointcut() {}
        
        // 定义前置通知
        @Before("myPointcut()")
        public void beforeAdvice() {
            // 执行逻辑代码
        }
        
        // 定义后置通知
        @After("myPointcut()")
        public void afterAdvice() {
            // 执行逻辑代码
        }
        
        // 其他通知方法...
    }
    
    1. 配置Spring AOP:在Spring的配置文件中,通过使用aop:config标签来配置AOP。
    <aop:config>
        <aop:aspect ref="myAspect">
            <aop:before method="beforeAdvice" pointcut-ref="myPointcut"/>
            <aop:after method="afterAdvice" pointcut-ref="myPointcut"/>
        </aop:aspect>
    </aop:config>
    
    1. 生成代理对象:Spring使用动态代理技术来生成代理对象,代理对象拦截目标对象的方法调用,并在切点处执行切面逻辑。
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    MyService myService = (MyService) context.getBean("myService"); 
    // 通过Spring容器获取被代理的对象
    myService.doSomething(); // 在此处触发切面逻辑的执行
    
    1. 执行切面逻辑:当调用被代理对象的方法时,代理对象会拦截对应的方法调用,并在切点处执行切面逻辑。

    通过上述步骤,Spring实现了切面的功能,通过提供的AOP相关注解和配置,我们可以方便地将切面逻辑和业务逻辑分离,提高了代码的可读性和可维护性。

    1年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部