- Spring动态代理的概念
- 概念:通过代理类为原始类或目标类增加额外功能
- 好处:利于原始类的维护
搭建开发环境
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.1.4.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.5.4</version><scope>runtime</scope></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.7</version><scope>runtime</scope></dependency>
Spring动态代理的开发步骤
创建原始对象(目标对象)
public class UserServiceImpl implements UserService{@Overridepublic void register(User user) {System.out.println("UserServiceImpl.register 业务运算+DAO");}@Overridepublic boolean login(String name, String password) {System.out.println("UserServiceImpl.login");return true;}}
额外功能
- MethodBeforeAdvice接口
- 额外的功能书写在接口的实现类中,运行在原始方法执行之前执行
public class Before implements MethodBeforeAdvice {/** 需要把运行在原始方法之前执行的额外功能书写在before方法中* */@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("Before.before");}}
- 额外的功能书写在接口的实现类中,运行在原始方法执行之前执行
- MethodBeforeAdvice接口
定义切入点
- 切入点:额外功能加入的位置
- 目的:由程序员根据需要,决定额外功能加入到哪个原始方法
- 简单的测试:所有方法都作为切入点,都加入原始功能
- 配置文件增加内容如下:
<aop:config><!--效果:所有方法都作为切入点--><aop:pointcut id="pc" expression="execution(* *(..))"/></aop:config>
- 配置文件增加内容如下:
组装(2、3整合)
- 配置文件如下
<aop:config><!--效果:所有方法都作为切入点--><aop:pointcut id="pc" expression="execution(* *(..))"/> //两个*之间有一个空格,固定格式,不可更改<!--组装:把额外功能与切入点整合--><aop:advisor advice-ref="before" pointcut-ref="pc"/></aop:config>
- 配置文件如下
调用
- 目的:获得Spring工厂创建的动态代理对象,并进行调用
ApplicationContext ctx=new ClassPathXMLApplicationContext(“applicationContxt.xml”);
注意:1. Spring工厂通过原始对象的id获得的对象是代理对象(规定如此)
2. 获得代理对象后,可以通过声明接口类型,存储代理对象
UserService UserService=ctx.getBean(“userService”);
- Spring动态代理细节分析
- Spring创建的动态代理类在哪?
- Spring框架在运行时,通过动态字节码技术,在JVM中创建,运行在JVM内部,等程序运行结束,和JVM一起消失
- 动态字节码技术:通过第三方动态字节码框架,在JVM中创建对应类的字节码,进而创建对象,当虚拟机结束,动态字节码跟着消失(如图所示)
- 结论:动态代理不需要定义类文件,都是JVM在运行过程中动态创建的,所以不会造成静态代理时类文件数量过多影响项目管理的问题
- Spring创建的动态代理类在哪?

- 动态代理编程会简化代理开发
- 在额外功能不改变的前提下,创建其他目标类(原始类)的代理对象时,只需指定原始对象(目标即可)
- 动态代理额外功能的维护性大大增强
