如果系统中有500个类,每个类都要添加日志功能,此时无论是直接修改源代码、继承还是组合,都是十分巨大的工作量。此时AOP可以帮我们解决这个问题。
现在假设记录日志的功能已经单独提出来了,由LogInterceptor来完成:
package com.bjsxt.aop;
public class LogInterceptor {
public void beforeMethod() {
System.out.println("logging...");
}
}
有了Spring AOP,我们就可以用配置文件来说明:“在某个类的每一个方法执行之前,都给我调用一次beforeMethod()方法”(更复杂一点的做法是给beforeMethod()方法添加一个Method参数,这样可以配置可以具体到某个类的某个方法上),如:
<beans>
<bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" >
<!-- 非标准写法,仅作演示 -->
<Log class="com.bjsxt.aop.LogInterceptor" logMethod="beforeMethod" targetMethod="all" />
</bean>
</beans>
这样,在配置文件中给500个bean都加上这么一段,就能给这500个类都加上日志功能了。
那么Spring AOP是如何实现的呢?用的是动态代理的方法。
参考[#0x0022],我们可以把LogInterceptor实现成一个InvocationHandler
package com.bjsxt.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class LogInterceptor implements InvocationHandler {
private Object target;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public void beforeMethod(Method m) {
System.out.println(m.getName() + ": logging...");
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
beforeMethod(m);
m.invoke(target, args);
return null;
}
}
调用的代码如下:
public class AOPTest
{
public static void main(String[] args)
{
UserDAO userDAO = new UserDAOImpl();
LogInterceptor li = new LogInterceptor();
li.setTarget(userDAO);
UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
userDAOProxy.save(new User());
}
}
这里要特殊说明的是:
(1) userDAOProxy对象是UserDAOImpl类的动态代理,userDAOProxy是代理对象,UserDAOImpl对象是被代理对象;
(2) 若想用Java API来给某个类(如UserDAOImpl)来创建动态代理,那么这个类必须实现一个接口(如UserDAO),没有实现接口的类用Java API是无法创建动态代理的(但cglib可以)。所以在Proxy.newProxyInstance()方法中,需要把被代理类的接口,即userDAO.getClass().getInterfaces()传递进去。
(3) 代理对象和被代理对象应该在同一个classLoader中,如果在不同的classLoader中,它们就无法互相访问,所以userDAO.getClass().getClassLoader()也作为参数传递给了Proxy.newProxyInstance()。代理对象和被代理对象需要互相访问的原因在(4)
(4) 我们得到的userDAOProxy对象,其类型应该是一个组合了LogInterceptor的类(li作为参数被传递给了Proxy.newProxyInstance()),而LogInterceptor又组合了userDAOImpl(li.setTarget(userDAO));加上userDAOProxy又实现了UserDAO接口,所以userDAOProxy看上去应该是这样一个类:
// 非标准写法,仅作演示用
public class UserDAOProxy implements UserDAO {
private InvocationHandler invocationHandler;
public UserDAOProxy(InvocationHandler invocationHandler) {
super();
this.invocationHandler = invocationHandler;
}
public InvocationHandler getInvocationHandler() {
return invocationHandler;
}
public void save(User user) {
this.invocationHandler.invoke(proxy, UserDAO.class.getDeclaredMethod("save", User.class), user);
}
}
(同[#0x0022],invoke()方法中的proxy对象还是不知道是干嘛用的……视频中说这个proxy对象就是userDAOProxy自身,待研究)
这样,Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li)也就相当于new UserDAOProxy(li)。userDAOProxy的save()方法的实际过程是:
Spring AOP为系统添加逻辑(业务逻辑,如上文的日志)的动态代理方法大抵就是这样。
如果UserDAO还有个delete()方法,那么userDAOProxy.delete()也会去调用li.invoke(proxy, delete, user)。这就体现了InvocationHandler是“对被代理对象的任意方法的invocation都handle”这么一个概念。
当然,更好的实现是把beforeMethod这部分逻辑提出来,让LogInterceptor这个类侧重“Interceptor”而不包含"Log"的逻辑,beforeMethod完全可以用一个Logger类来实现
- 大小: 10.5 KB
分享到:
相关推荐
Spring AOP 入门 作者:廖雪峰
spring之AOP(动态代理),包括jdk动态代理和CGLib动态代理
主要对Spring AOP的相关概念和简单的静态代理、动态代理以及常见的几种AOP配置方式做总结学习。主要包括:1. AOP的常见概念 2. 静态代理 3. jdk动态代理 4. Aspectj and Aspectjweaver 5. **aop-config** 6. CGLIB ...
Spring AOP 代理一、两种代理方式1. JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。二
SpringAOP动态代理 Spring AOP 使用的动态代理主要有两种方式:JDK 动态代理和 CGLIB 代理。 JDK 动态代理:用于代理实现了接口的类。Spring 会使用 java.lang.reflect.Proxy 类来创建代理对象。 CGLIB 代理:用于...
AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理
赠送jar包:spring-aop-5.0.10.RELEASE.jar; 赠送原API文档:spring-aop-5.0.10.RELEASE-javadoc.jar; 赠送源代码:spring-aop-5.0.10.RELEASE-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.0.10.RELEASE....
springAOP配置实现动态代理,有利于熟悉动态代理原理,深入了解spring。
SpringAOP之探秘(动态代理、责任链模式、注解使用)- 详情:https://blog.csdn.net/Dream_Weave/article/details/85008674
package com.gc.dynproxy下为:aop方式动态代理 package com.gc.javaproxy下为:java代理机制实现 package com.gc.proxy下为:自定义代理模式(面向接口编程) package com.gc.normal下为:通用日志处理方式
通过动态代理模拟Spring AOP,通过动态代理模拟Spring AOP
死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序
Spring源码最难问题:当Spring AOP遇上循环依赖.docx
Spring-AOP-利用java中的动态代理和Spring的拦截器做到AOP
spring-aop-1.1.1.jar spring-aop-1.2.6.jar spring-aop-1.2.9.jar spring-aop-2.0.2.jar spring-aop-2.0.6.jar spring-aop-2.0.7.jar spring-aop-2.0.8.jar spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-...
spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop
spring aop jar 包
Spring AOP面向方面编程原理:AOP概念,主要介绍面向对象的概念及原理,及作者的一些理解。
此资源为文章中《代理设计模式:静态代理和动态代理的理解、实现与区别(优缺点)》与《 AOP动态代理声明式的3种配置方式过程与区别》的案例代码,可下载参考学习。