AOP:面向切面、面向方面、面向接口是一种横切技术
横切技术运用:
1.事务管理: (1)数据库事务:(2)编程事务(3)声明事物:Spring AOP-->声明事物   
2.日志处理:
3.安全验证: Spring AOP---OOP升级

静态代理原理:目标对象:调用业务逻辑    代理对象:日志管理
表示层调用--->代理对象(日志管理)-->调用目标对象

动态代理原理:spring AOP采用动态代理来实现
(1)实现InvocationHandler接口

(2)创建代理类(通过java API)

Proxy.newProxyInstance(动态加载代理类,代理类实现接口,使用handler);

(3)调用invoke方法(虚拟机自动调用方法)

日志处理
 //调用目标对象
 method.invoke("目标对象","参数");
 日志处理

通过代理对象--(请求信息)-->目标对象---(返回信息)----> 代理对象

Spring 动态代理中的基本概念

1、关注点(concern)
   一个关注点可以是一个特定的问题,概念、或者应用程序的兴趣点。总而言之,应用程序必须达到一个目标
   安全验证、日志记录、事务管理都是一个关注点
   在oo应用程序中,关注点可能已经被代码模块化了还可能散落在整个对象模型中
2、横切关注点(crosscutting concern)
   如何一个关注点的实现代码散落在多个类中或方法中
3、方面(aspect)
   一个方面是对一个横切关注点模块化,它将那些原本散落在各处的,
   用于实现这个关注点的代码规整在一处
4、建议(advice)通知
   advice是point cut执行代码,是方面执行的具体实现
5、切入点(pointcut)
   用于指定某个建议用到何处
6、织入(weaving)
   将aspect(方面)运用到目标对象的过程
7、连接点(join point)
  程序执行过程中的一个点

通知类型:
  try{
    //前置通知
         //环绕通知
            //调用目标对象方法
         //环绕通知
    //后置通知
  }catch(){
    //异常通知
  }finally{
    //终止通知
  }

流程图

一.静态代理原理实例:

项目结构图:

IUserServ接口代码

  1. public interface IUserServ {
  2. List<User> findAllUser();
  3. int deleteUserById(User user);
  4. int saveUser(User user);
  5. }

UserServImpl实现类代码

  1. public class UserServImpl implements IUserServ {
  2. public int deleteUserById(User user) {
  3. System.out.println("******执行删除方法******");
  4. return 0;
  5. }
  6. public List<User> findAllUser() {
  7. System.out.println("*******执行查询方法*******");
  8. return null;
  9. }
  10. public int saveUser(User user) {
  11. System.out.println("*******执行添加方法********");
  12. return 0;
  13. }
  14. }

UserServProxyImpl实现类代码

  1. //代理类:完成日志输出
  2. public class UserServProxyImpl implements IUserServ {
  3. // 访问目标对象(UserServImpl)
  4. // 代理对象(UserServProxyImpl)
  5. // 创建目标对象
  6. private IUserServ iuserServ ;//= new UserServImpl();
  7. public UserServProxyImpl(IUserServ iuserServ){
  8. this.iuserServ = iuserServ;
  9. }
  10. public int deleteUserById(User user) {
  11. beforeLog();
  12. //调用目标对象里方法
  13. iuserServ.deleteUserById(user);
  14. afterLog();
  15. return 0;
  16. }
  17. public List<User> findAllUser() {
  18. beforeLog();
  19. //调用目标对象里方法
  20. iuserServ.findAllUser();
  21. afterLog();
  22. return null;
  23. }
  24. public int saveUser(User user) {
  25. beforeLog();
  26. //调用目标对象里方法
  27. iuserServ.saveUser(user);
  28. afterLog();
  29. return 0;
  30. }
  31. private void beforeLog() {
  32. System.out.println("开始执行");
  33. }
  34. private void afterLog() {
  35. System.out.println("执行完毕");
  36. }
  37. }

ActionTest测试类代码

  1. public class ActionTest {
  2. public static void main(String[] args) {
  3. //用户访问代理对象---信息->目标对象
  4. IUserServ iuserServ = new UserServProxyImpl(new UserServImpl());
  5. iuserServ.findAllUser();
  6. }
  7. }

运行结果:

开始执行
*******执行查询方法*******
执行完毕
二.动态代理实例

项目结构图:

IUserServ接口代码与UserServImpl实现类代码和上述代码相同

LogHandler类代码

  1. public class LogHandler implements InvocationHandler {
  2. //目标对象
  3. private Object targetObject;
  4. /**
  5. * 创建动态代理类
  6. * @return object(代理类)
  7. */
  8. public Object createProxy(Object targetObject){
  9. this.targetObject = targetObject;
  10. return Proxy.newProxyInstance(
  11. targetObject.getClass().getClassLoader(),
  12. targetObject.getClass().getInterfaces(), this);
  13. }
  14. @Override
  15. public Object invoke(Object proxy, Method method, Object[] args)
  16. throws Throwable {
  17. Object obj = null;
  18. try {
  19. beforeLog();
  20. //obj: 目标对象--->代理对象的返回值--->返回给调用者的信息
  21. //this.invoke("目标对象","代理对象给目标对象传递参数");
  22. //调用目标对象中方法
  23. obj = method.invoke(targetObject, args);
  24. afterLog();
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27. }
  28. return obj;
  29. }
  30. //日志管理方法
  31. private void beforeLog(){
  32. System.out.println("开始执行");
  33. }
  34. private void afterLog(){
  35. System.out.println("执行完毕");
  36. }
  37. }

ActionTest测试类代码:

  1. public class ActionTest {
  2. public static void main(String[] args) {
  3. //创建代理对象iuserServ
  4. LogHandler handler = new LogHandler();
  5. IUserServ iuserServ = (IUserServ)handler.createProxy(new UserServImpl());
  6. iuserServ.deleteUserById(new User());
  7. }
  8. }

运行结果:
开始执行
******执行删除方法******
执行完毕
三.Spring AOP使用(2.x版本之前)

项目结构图:



IUserServ接口代码与UserServImpl实现类代码和上述代码相同

配置步骤:

1、配置目标对象(applicationContext.xml)

  1. <bean id="userServTarget" class="com.tarena.biz.impl.UserServImpl"/>

2、配置通知
(a)前置通知(BeforeLogAdvice)

  1. public class BeforeLogAdvice implements MethodBeforeAdvice {
  2. /**
  3. * Method method:调用目标对象的方法
  4. * Object[] args:发送给目标对象的参数列表
  5. * Object target:目标对象
  6. */
  7. public void before(Method method, Object[] args, Object target)
  8. throws Throwable {
  9. beforeLog();
  10. }
  11. private void beforeLog(){
  12. System.out.println("开始执行");
  13. }
  14. }

(b)后置通知(AfterLogAdvice)

  1. public class AfterLogAdvice implements AfterReturningAdvice {
  2. /**
  3. * Object returnValue:目标对象返回值
  4. *  Method method:目标对象方法名
  5. *  Object[] args:目标对象参数列表
  6. *  Object target:目标对象
  7. */
  8. public void afterReturning(Object returnValue, Method method,
  9. Object[] args, Object target) throws Throwable {
  10. afterLog();
  11. }
  12. private void afterLog(){
  13. System.out.println("执行完毕");
  14. }
  15. }

(c)在spring容器中,让容器管理通知(applicationContext.xml)

  1. <!-- 定义通知 -->
  2. <!-- 前置通知 -->
  3. <bean id="beforeLogAdvice" class="com.tarena.advice.BeforeLogAdvice"/>
  4. <!-- 后置通知 -->
  5. <bean id="afterLogAdvice" class="com.tarena.advice.AfterLogAdvice"/>

3、配置代理对象(applicationContext.xml)

  1. <!-- 代理类作用: 生成代理类,织入通知 -->
  2. <bean id="userServProxy"
  3. class="org.springframework.aop.framework.ProxyFactoryBean">
  4. <property name="interfaces">
  5. <!-- 可以添加多个接口 -->
  6. <list>
  7. <value>com.tarena.biz.IUserServ</value>
  8. </list>
  9. </property>
  10. <!-- 引入通知 -->
  11. <property name="interceptorNames">
  12. <list>
  13. <value>beforeLogAdvice</value>
  14. <value>afterLogAdvice</value>
  15. </list>
  16. </property>
  17. <!-- 目标对象 -->
  18. <property name="target" ref="userServTarget"/>
  19. </bean>

4.访问()
Spring容器:通过代理对象调用-->织入通知--->目标对象
程序员:访问代理对象

测试类(ActionTest):

  1. public class ActionTest {
  2. public static void main(String[] args) {
  3. ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
  4. IUserServ iuserServ = (IUserServ)ac.getBean("userServProxy");
  5. iuserServ.deleteUserById(new User());
  6. iuserServ.findAllUser();
  7. }
  8. }

运行结果:

开始执行
******执行删除方法******
执行完毕
开始执行
*******执行查询方法*******
执行完毕
四.Spring AOP使用(2.x版本之后)这种方式需要额外添加两个jar包,

存放位置在spring-framework-2.5.6.SEC01\lib\aspectj文件夹下。

项目结构图


IUserServ接口代码与UserServImpl实现类代码和上述代码相同

LogAdvice中

  1. public class LogAdvice {
  2. public void beforeLog(){
  3. System.out.println("开始执行");
  4. }
  5. public void afterLog(){
  6. System.out.println("执行完毕");
  7. }
  8. }

applicationContext.xml中

  1. <!-- spring2.x后 -->
  2. <!-- 目标对象 -->
  3. <bean id="userServImpl" class="com.tarena.biz.impl.UserServImpl"/>
  4. <!-- 通知 -->
  5. <bean id="logAdvice" class="com.tarena.advice.LogAdvice"/>
  6. <aop:config>
  7. <aop:aspect id="logAspect" ref="logAdvice">
  8. <!-- 切入点 -->
  9. <aop:pointcut id="beforePointCut"
  10. expression="execution(* saveUser*(..))"/>
  11. <aop:pointcut id="afterPointCut"
  12. expression="execution(* saveUser*(..))"/>
  13. <!-- 织入(通知作用于切入点) -->
  14. <aop:before method="beforeLog" pointcut-ref="beforePointCut"/>
  15. <aop:after method="afterLog" pointcut-ref="afterPointCut"/>
  16. </aop:aspect>
  17. </aop:config>

测试类:

  1. public class ActionTest {
  2. public static void main(String[] args) {
  3. ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
  4. IUserServ iuserServ = (IUserServ)ac.getBean("userServImpl");
  5. iuserServ.deleteUserById(new User());
  6. iuserServ.findAllUser();
  7. iuserServ.saveUser(new User());
  8. }
  9. }

运行结果
******执行删除方法******
*******执行查询方法*******
开始执行
*******执行添加方法********
执行完毕

注:如果要在业务层所有的方法前后添加日志文件,则需要更改为以下配置

  1. <aop:pointcut id="beforePointCut"
  2. expression="execution(* com.tarena.biz.*.*(..))"/>
  3. <aop:pointcut id="afterPointCut"
  4. expression="execution(* com.tarena.biz.*.*(..))"/>

运行结果:

开始执行
******执行删除方法******
执行完毕
开始执行
*******执行查询方法*******
执行完毕
开始执行
*******执行添加方法********
执行完毕

最新文章

  1. [DFNews] EnCase v7.08发布
  2. Vcenter server 5.5克隆模板(创建ISO镜像)
  3. 我的android学习经历32
  4. Linux/UNIX脚本中 $0,$1,$2的含义
  5. javascript中获取非行间样式的方法
  6. apache-tomcat-9安装以及与eclipse结合
  7. Thrift的安装和简单演示样例
  8. (十)boost库之多线程
  9. UVA 10305 Ordering Tasks
  10. Http权威指南笔记(一) URI URL URN 关系
  11. Nagios+pnp4nagios+rrdtool 安装配置为nagios添加自定义插件(三)
  12. Android 应用程序崩溃日志捕捉
  13. 关于前端js面向对象编程以及封装组件的思想
  14. Filebeat6.31整合Kafka集群消息队列(三)
  15. JMD Handy Baby 2 to Decode &amp; Adding New BMW 525 ID46 Key
  16. error C3861: “xxxx”: 找不到标识符
  17. HTTP基本原理(转)
  18. odoo开发笔记--odoo可用小图标
  19. Sagas模式
  20. 自动布局又出问题-HPPGCTableViewCell

热门文章

  1. USB协议枚举过程详解
  2. 初识Identity(二)
  3. BZOJ1816 CQOI2010 扑克牌 贪心
  4. 移动端高清适配方案(解决图片模糊问题、1px细线问题)
  5. [尝鲜]妈妈再也不用担心 dotnet core 程序发布了: .NET Core Global Tools
  6. 记一次在.NET成长之路上的下午茶
  7. Openstack架构概念图-简单汇总
  8. 利用阿里云的源yum方式安装Mongodb
  9. &lt;软件体系结构&gt;实验框架选择及其说明
  10. 【评分】Alpha阶段