Spring 从入门到精通 (十二) 动态代理
关键词:Spring | 动态代理
一、创建原始对象(目标对象)
原始对象,即需要被代理的对象,常见的比如业务对象
UserServiceImpl
public class UserServiceImpl implements UserService{ @Override public void register(User user) { System.out.println("UserServiceImpl register + DAO"); } @Override public boolean login(String name, String pwd1) { System.out.println("UserServiceImpl login + DAO"); return true; } }
并在Spring工厂中配置
spring.xml
<bean class="com.liu.service.UserServiceImpl" id="userService"/>
二、开发额外功能
实现 MethodBeforeAdvice 接口,把额外功能写在实现类上,它会在原始方法执行前执行
Before
public class Before implements MethodBeforeAdvice { /* 在原始方法执行前执行的额外功能 */ @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("-------- MethodBeforeAdvice log... -------"); } }
在工厂配置
spring.xml
<bean class="com.liu.proxy.Before" id="before"/>
三、创建切入点
切入点是指额外功能需要作用在哪些包或哪些类上甚至哪些方法上
下面配置的意思是,配置了一个id为pc的切入点,切的范围是所有方法
spring.xml
<aop:config> <aop:pointcut id="pc" expression="execution(* *(..))"/> </aop:config>
四、组装切面
切面 = 额外功能 + 切入点
所有方法都加入before额外功能
<aop:advisor advice-ref="before" pointcut-ref="pc"/>
五、测试
获取Spring工厂创建的代理类并调用
注意:
Spring规定通过原始对象的 id 获取的就是代理对象
获取代理对象,可以使用声明接口的类型,进行存储
所以,测试代码应该这样写:
@Test public void t2(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml"); UserService userService = (UserService) context.getBean("userService"); userService.login("123","1232"); userService.register(new User()); }
-------- MethodBeforeAdvice log... ------- UserServiceImpl login + DAO -------- MethodBeforeAdvice log... ------- UserServiceImpl register + DAO
六、细节分析
6.1、代理类在哪呢?
代理类是通过动态字节码技术,在JVM创建的,运行在JVM内部,程序结束,会和JVM一起消失
6.2、什么是动态字节码技术?
通过第三方动态字节码框架,在JVM机中创建对应类的字节码,进而创建对象,但虚拟机结束,动态字节码也随之消失
七、写在最后
座右铭:不要在乎别人如何看你,要在乎你自己如何看未来,看梦想,看世界…!