Spring动态代理的简单实现

原始对象(接口+实现)

UserService

package com.yusian.service;

import com.yusian.domain.User;

public interface UserService {

    void register(User user);

    boolean login(String username, String password);

}

UserServiceImpl

package com.yusian.service;

import com.yusian.domain.User;

public class UserServiceImpl implements UserService{
    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register--------原始功能");
    }

    @Override
    public boolean login(String username, String password) {
        System.out.println("UserServiceImpl.login--------原始功能");
        return false;
    }
}

附加对象(实现MethodBeforeAdvice接口)

Before

package com.yusian.aop;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Before implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("Before.before----------------附加功能: " + o);
    }
}

AOP组装

引用相关依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.3.3</version>
    </dependency>

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.9.6</version>
    </dependency>

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.6</version>
    </dependency>
</dependencies>

Spring配置

<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.yusian.service.UserServiceImpl"/>

    <bean id="before" class="com.yusian.aop.Before"/>

    <aop:config>
        <aop:pointcut id="pc" expression="execution(* *(..))"/>
        <aop:advisor advice-ref="before" pointcut-ref="pc"/>
    </aop:config>

</beans>

AOP: Aspect Oriented Programming 面向切面编程

​ 如果拿对象的生命周期来对标的话,这个所谓的切面就是生命周期中的某一个时刻点。整个生命周期中会有多个方法,在不同的时期调用,面向切面指的就是不同的生命周期方法

pointcut: 切入点就是指在某些方法前增加一个生命周期方法,在此之前先调用所谓的切入点,然后再按原来的流程或顺序执行,以达到我们需要的效果,这是一种思想。

​ Spring通过配置文件中增加标签,告诉Spring框架,需要在哪些方法前切入什么,两个关键点:哪些方法切入什么,分别对应expression表达式与实现MethodBeforeAdvice接口

实现与测试

@Test
public void dynamicProxyTest() {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = ctx.getBean("userService", UserService.class);
    userService.register(new User());
}

输出结果:

Before.before----------------附加功能: com.yusian.service.UserServiceImpl@6dc17b83
UserServiceImpl.register--------原始功能

Process finished with exit code 0

One thought on “Spring动态代理的简单实现

  1. Pingback: Spring动态代理中切入点表达式的基本使用 | 年年有"余"

Leave a Reply