Spring AOP(面向切面编程)【Spring AOP的技术基础】
2014-07-30 15:46
363 查看
Spring框架的AOP组件基于JDK的动态代理或者CGLIB代理实现,
其中JDK动态代理是使用较多的技术,动态代理是面向对象的代理(proxy)模式(GoF23)的一种动态实现。
代理模式
代理模式是一种结构型设计模式。当客户端不想直接调用主题对象,而希望在主题对象的行为前后加上预处理或者后续处理时,则可以使用代理模式。
代理模式中往往包含以下三种角色:
1、主题抽象类(Subject)
主题抽象类中定义了主题对象的行为,上述主题抽象类定义了主题对象的request行为。
2、实际主题类(RealSubject)
3、代理类(ProxySubject)
代理类中定义了preRequest和postRequest方法,对实际主题类中的request方法实施了控制。
代理类对应Spring AOP中的ProxyFactoryBean类,用来生成代理对象,代理对象将Advice织入,从而对目标对象的方法进行了控制。
动态代理
动态代理是在运行时实现代理模式的方法,Java的JDK对其进行了实现。
JavaSE中实现动态代理的主要类有两个,如下所述:
1、java.lang.reflect.Proxy类,该类中提供获得代理类对象的方法
2、java.lang.reflect.InvocationHandler接口,该接口中提供了invoke方法,能够调用代理对象的方法。
上述代码中的invoke方法,创建了CustomerServiceImpl类的实例service,然后向日志文件中添加日志信息,
最后使用method。invoke(service,args)调用了service实例的方法。
在invoke方法中,可以根据实际需要对目标类CustomerServiceImpl的方法实施控制,例如上述代码中使用Logger.log实现了日志功能。
完成CustomerServiceInvocationHandler类后,可以使用Proxy类生成代理对象,代码如下:
然后通过代理对象调用login方法,运行后将在日志文件中记录如下信息:
同事将在控制台打印输出如下信息:
Spring框架在动态代理的基础上,进一步使用了IoC容器生成代理对象,而不需要实现InvocationHandler接口,从而实现了Spring框架的AOP编程思想。
可见,Spring的AOP框架也是基于IoC基础上实现的技术。
其中JDK动态代理是使用较多的技术,动态代理是面向对象的代理(proxy)模式(GoF23)的一种动态实现。
代理模式
代理模式是一种结构型设计模式。当客户端不想直接调用主题对象,而希望在主题对象的行为前后加上预处理或者后续处理时,则可以使用代理模式。
代理模式中往往包含以下三种角色:
1、主题抽象类(Subject)
abstract public class Subject{ abstract public void request(); }
主题抽象类中定义了主题对象的行为,上述主题抽象类定义了主题对象的request行为。
2、实际主题类(RealSubject)
public class RealSubject extends Subject{ public RealSubject(){ } public void request(){ System.out.println("From real subject.") } }实际主题类继承了抽象主题类Subject,实现了抽象主题类中的行为request,实际主题类即AOP中的目标对象。
3、代理类(ProxySubject)
public class ProxySubject extends Subject{ private RealSubject realSubject; public ProxySubject(){ } public void request(){ preRequest(); if(realSubject==null){ realSubject = new RealSubject(); } realSubject.request(); postRequest(); } private void preRequest(){ //something you want to do before requesting } private void postRequest(){ //something you want to do after requesting } }代理类继承了抽象主题类,同时关联了实际主题类。
代理类中定义了preRequest和postRequest方法,对实际主题类中的request方法实施了控制。
代理类对应Spring AOP中的ProxyFactoryBean类,用来生成代理对象,代理对象将Advice织入,从而对目标对象的方法进行了控制。
动态代理
动态代理是在运行时实现代理模式的方法,Java的JDK对其进行了实现。
JavaSE中实现动态代理的主要类有两个,如下所述:
1、java.lang.reflect.Proxy类,该类中提供获得代理类对象的方法
newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)该方法能够返回代理对象。
2、java.lang.reflect.InvocationHandler接口,该接口中提供了invoke方法,能够调用代理对象的方法。
package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Date; import log.Logger; import org.apache.commons.dbcp.BasicDataSource; import service.CustomerServiceImpl; import dao.Impl.CustomerDAOImpl; public class package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Date; import log.Logger; import org.apache.commons.dbcp.BasicDataSource; import service.CustomerServiceImpl; import dao.Impl.CustomerDAOImpl; public class CustomerServiceInvocationHandler implements InvocationHandler { <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public Object invoke(Object proxy, Method method, Object[] args) <span style="white-space:pre"> </span>throws Throwable { <span style="white-space:pre"> </span>BasicDataSource dataSource = new BasicDataSource(); <span style="white-space:pre"> </span>dataSource.setDriverClassName("com.mysql.jdbc.Driver"); <span style="white-space:pre"> </span>dataSource.setUrl("jdbc:mysql://localhost:3306/mldn"); <span style="white-space:pre"> </span>dataSource.setUsername("root"); <span style="white-space:pre"> </span>dataSource.setPassword("password"); <span style="white-space:pre"> </span>dataSource.setMaxActive(10); <span style="white-space:pre"> </span>dataSource.setInitialSize(2); <span style="white-space:pre"> </span>CustomerDAOImpl dao = new CustomerDAOImpl(); <span style="white-space:pre"> </span>dao.setDataSource(dataSource); <span style="white-space:pre"> </span>CustomerServiceImpl service = new CustomerServiceImpl(); <span style="white-space:pre"> </span>service.setDao(dao); <span style="white-space:pre"> </span>Logger.log(method.getName()+" : "+new Date()); <span style="white-space:pre"> </span>return method.invoke(service, args); <span style="white-space:pre"> </span>} }
上述代码中的invoke方法,创建了CustomerServiceImpl类的实例service,然后向日志文件中添加日志信息,
最后使用method。invoke(service,args)调用了service实例的方法。
在invoke方法中,可以根据实际需要对目标类CustomerServiceImpl的方法实施控制,例如上述代码中使用Logger.log实现了日志功能。
完成CustomerServiceInvocationHandler类后,可以使用Proxy类生成代理对象,代码如下:
package test; import java.lang.reflect.Proxy; import proxy.CustomerServiceInvocationHandler; import service.CustomerService; public class TestProxy { public static void main(String[] args) { CustomerService serviceProxy=(CustomerService) Proxy.newProxyInstance(CustomerService.class.getClassLoader(), new Class[]{CustomerService.class}, new CustomerServiceInvocationHandler()); System.out.println(serviceProxy.login("tom", "tom")); } }上述代码中,使用Proxy类中的newProxyInstance方法返回CustomerServiceImpl的代理对象,代理对象的类型就是CustomerService接口类型。
然后通过代理对象调用login方法,运行后将在日志文件中记录如下信息:
Wed Jul 30 16:22:41 CST 2014: login : Wed Jul 30 16:22:41 CST 2014
同事将在控制台打印输出如下信息:
invoke login... true
Spring框架在动态代理的基础上,进一步使用了IoC容器生成代理对象,而不需要实现InvocationHandler接口,从而实现了Spring框架的AOP编程思想。
可见,Spring的AOP框架也是基于IoC基础上实现的技术。
相关文章推荐
- 面向对象技术基础
- javascript 面向对象技术基础教程第1/2页
- Java面试--Spring技术要点--Spring AOP(面向切面编程)
- Spring基础、IOC(控制反转)、AOP(面向切面编程)、Log4j、注解配置
- 深入探索spring技术内幕(七): 配置Spring AOP面向切面编程
- 软件架构训练基础教程之面向组件技术
- 软件架构训练基础教程之面向组件技术
- 软件架构训练基础教程之面向组件技术
- Spring AOP(面向切面编程)【使用Advisor】
- 面向对象技术基础总结
- javascript 面向对象技术基础教程第1/2页
- 面向服务架构十大技术与基础理论
- [转载]面向非射频测试工程师的射频测量技术基础
- 面向对象技术——UML基础
- 面向对象技术基础
- [推荐]javascript 面向对象技术基础教程
- Spring AOP( 面向切面编程)配置
- javascript面向对象技术基础(四)(类、构造函数、原型)
- 面向对象类间关系 摘自【java核心技术 卷1 基础知识 原书第8版】
- 深入探索spring技术内幕(七): 配置Spring AOP面向切面编程