• spring03


    一、aop思想介绍

      

      1、这里,以三个例子来说明:

        (1)Filter过滤器,将每次都要在servlet里写的解决乱码的代码提取出来,放在一个过滤器Filter中,使得在客户端请求到达servlet(servlet响应到达客户端页面)之前,先经过过滤器,处理编码问题;

        

        (2)事务管理(动态代理中使用aop,体现了aop思想):之前在service层,都要写事物的开启、提交(回滚等),运用aop思想之后,将之前service里的事务管理的代码提取出来,放到InvocationHandler里,然后通过动态代理的方式,将InvocationHandler动态的添加到所有的service层的类当中,形成代理对象;    

             

        (3)struts2中的action赋值操作放在拦截器中进行;

        

    二、spring中的aop思想

      1、spring中的aop思想指的是:spring能够为容器中所存放的对象生成动态代理对象;之前我们使用aop思想时,比如上述一中的InvocationHandler事务管理,需要我们自己手动写代码(proxy.newProxyInstanse(classload,interface[] arr,InvocationHandler  handler)),创建并生成代理对象,而现在,spring会为我们做这些事(通过xml配置或注解的方式),生成代理对象,在生成动态代理这个过程中会给每个service里的方法添加事务管理的代码;

      2、spring实现aop的原理:

        依赖于两种代理技术:

        (1)动态代理:要求被代理对象必须要实现接口,才能产生代理对象,如果没有接口,将不能使用动态代理的技术;

        (2)cglib代理:第三方代理技术,可以对任何类生成代理对象,代理原理是对目标对象进行继承代理;比如,我要给UserService(的对象userService)生成一个代理对象,实际上生成的这个UserService的代理对象是UserService对象的子类,即它会对被代理对象进行继承(对被代理对象进行继承代理),所以如果目标对象(目标类)被final修饰,那么该类无法cglib代理;

        结论:以上两种代理技术的区别:从代理对象和被代理对象的角度来说;动态代理中,代理对象和被代理对象之间没有继承关系,只是实现了同一个接口比如UserviceImpl实现了Uservice接口,代理对象生成时,第二个参数就是被代理对象的接口UserServiceImpl.class.getInterfaces(),即也实现了Uservice接口;cglib代理中,代理对象和被代理对象是继承关系,即代理对象是被代理对象的子类;

      结论:spring中会混合使用上述两种代理技术实现aop,优先使用动态代理的技术(1),如果没有接口的话,再使用cglib代理技术(2);

      3、这里我们说一下手动实现以上两种代理的代码(仅做了解,以后开发中spring会帮我们实现):

       (1)动态代理:

        首先来看这个方法:proxy.newProxyInstanse(classload,interface[] arr,InvocationHandler  handler)

        上述这个函数,用于我们手动利用动态代理技术生成代理对象,这个方法定义在代理工厂类里,比如UserServiceProxyFactory里,里边的三个参数:

          classload:UserServiceProxyFactory.class.getClassLoader(),

          interface [] arr:被代理对象的接口,UserServiceImpl.class.getInterfaces(),

          handler:第三个参数,决定了本次代理到底要怎么增强我们的目标方法,增强的内容;

                这是一个接口InvocationHandler的对象,接口是不能创建对象的,但这里这么写成对象,必须要实现接口里的方法(接口回调),如下:

     1 package cn.itcast.c_proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 import java.lang.reflect.Proxy;
     6 
     7 import cn.itcast.service.UserService;
     8 import cn.itcast.service.UserServiceImpl;
     9 //观光代码=>动态代理
    10 public class UserServiceProxyFactory implements InvocationHandler {
    11     
    12     public UserServiceProxyFactory(UserService us) {
    13         super();
    14         this.us = us;
    15     }
    16 
    17     private UserService us;
    18     
    19     public UserService getUserServiceProxy(){
    20         //生成动态代理
    21         UserService usProxy = (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
    22                                     UserServiceImpl.class.getInterfaces(), 
    23                                     this);
    24         //返回
    25         return usProxy;
    26         
    27     }
    28 
    29     @Override
    30     public Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable {
    31         System.out.println("打开事务!");
    32         Object invoke = method.invoke(us, arg2);
    33         System.out.println("提交事务!");
    34         return invoke;
    35     }//这部分代码就是为了proxy.newProxyInstanse(classload,interface[] arr,InvocationHandler  handler)中第三个参数写的,实现接口
        //InvocationHandler中的方法incoke(),只不过,直接在UserServiceProxyFactory基础上实现接口,参数用this来代替; 
    36 
    37 }

      然后写一个测试类,来测试上述的代码:

        

      (2)cglib代理(直接放上代码)

        
     1 package cn.itcast.c_proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 import java.lang.reflect.Proxy;
     6 
     7 import org.springframework.cglib.proxy.Callback;
     8 import org.springframework.cglib.proxy.Enhancer;
     9 import org.springframework.cglib.proxy.MethodInterceptor;
    10 import org.springframework.cglib.proxy.MethodProxy;
    11 
    12 import cn.itcast.service.UserService;
    13 import cn.itcast.service.UserServiceImpl;
    14 
    15 //观光代码=>cglib代理
    16 public class UserServiceProxyFactory2 implements MethodInterceptor {
    17     
    18 
    19     public UserService getUserServiceProxy(){
    20         
    21         Enhancer en = new Enhancer();//帮我们生成代理对象
    22         
    23         en.setSuperclass(UserServiceImpl.class);//设置对谁进行代理
    24         
    25         en.setCallback(this);//代理要做什么
    26         
    27         UserService us = (UserService) en.create();//创建代理对象
    28         
    29         return us;
    30     }
    31 
    32     @Override
    33     public Object intercept(Object prxoyobj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
    34         //打开事务
    35         System.out.println("打开事务!");
    36         //调用原有方法
    37         Object returnValue = methodProxy.invokeSuper(prxoyobj, arg);
    38         //提交事务
    39         System.out.println("提交事务!");
    40         
    41         return returnValue;
    42     }
    43 
    44 
    45 }
    手动实现cglib代理

      我们将上述的代码提出一部分简单分析一下:

        这里边使用了一个增强类Enhancer类,帮助我们生成代理对象,以增强目标方法(除了我们本身的方法,还有额外的方法)

     1 public UserService getUserServiceProxy(){
     2         
     3         Enhancer en = new Enhancer();//帮我们生成代理对象
     4         
     5         en.setSuperclass(UserServiceImpl.class);//设置对谁进行代理
     6         
     7         en.setCallback(this);//代理要做什么,Callback是一个接口,也要实现这个接口,就像动态代理中的InvocationHandler,
     8         
     9         UserService us = (UserService) en.create();//创建代理对象
    10         
    11         return us;
    12 }
  • 相关阅读:
    ubuntu 安装PHP
    修改rm 防止误删除
    游标输出
    微软已经提供了好几个开源的小项目供学习参考
    数据库存取时间比较
    UML建模工具比较
    16进制与BYTE类型转换
    显示有换行字符的提示框
    ORACLE数据库中主要字段类型的读写例子(包括:Long、Raw、Blob)
    .net 动态sql 参数应用 oracle和sql server的比较
  • 原文地址:https://www.cnblogs.com/limuma/p/8463695.html
Copyright © 2020-2023  润新知