#千锋逆战# 动态代理AOP(1)

动态代理

  1. jdk代理方式

    1. 新建接口

      • public interface IUserService<T> {
        
            /**
             * 获取所有的用户对象列表
             * @return
             */
            List<T> getAllUser();
        
            /**
             * 保存用户
             * @param user
             * @return
             */
            boolean saveUser(T user);
        
            /**
             * 根据用户uid删除该uid对应的用户信息
             * @param uid
             * @return
             */
            boolean deleteUser(int uid);
        
            /**
             * 更新指定用户信息
             * @param obj
             * @return
             */
            boolean updateUser(T obj);
        }
        
    2. 实现接口

    3. 实现代理方法

      • public class UserFactory {
        
            public static IUserService getUserService(){
        
                IUserService us = new UserservcieImpl();//被代理的对象
        
                MyAspect ma = new MyAspect();//需要添加的代理
        
                /**
                 * @param UserFactory.class.getClassLoader() 类加载器,用来加载代理类
                 * @param us.getClass().getInterfaces() 被代理的接口
                 * @param new InvocationHandler() 内部类 重写invoke方法
                 */
                IUserService ius = (IUserService) Proxy.newProxyInstance(UserFactory.class.getClassLoader()
                        , us.getClass().getInterfaces(), new InvocationHandler() {
        
                    /**
                     * 代理对象调用的回掉方法
                     * @param proxy 代理对象
                     * @param method 被代理的方法
                     * @param args 被代理方法的参数列表对象
                     * @return 每个方法的最终返回值
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
                        ma.before();
        
                        Object obj = method.invoke(us, args);//原方法
        
                        ma.after();
        
                        return obj;
                    }
                });
        
                return ius;
            }
        }
        
  2. cglib代理方式

    1. 与jdk代理相似,代理方法有所不同

    2. 基本原理

      • 使用Enhancer生成原有类的子类,设置好回掉(callback),那么原有类的所有方法都会被拦截然后调用实现了MethodInterceptor的intercept()方法.
    • 提示:如果原方法是final类型的,则MethodInterceptor无法拦截
    1. 代理方法

      • public class UserFactory {
        
            /**
             * 使用Spring中的一个增强类来实现aop方式
             *      1.  创建Enhancer对象
             *      2.  设置增强类Enhancer的superClass
             *      3.  设置Enhancer对象的回调
             *      4.  通过eh对象的create()方法来得到指定的对象
             * @return
             */
            public static IUserService getUserService(){
                //  1.  创建Enhancer对象
                Enhancer eh = new Enhancer();
                //  2.  设置增强类Enhancer的superClass
                eh.setSuperclass(IUserService.class);
        
                IUserService<Object> us = new UserServiceImpl<>();//需要代理的对象
                MyAspect ma = new MyAspect();//
                //  3.  设置Enhancer对象的回调
                eh.setCallback(new MethodInterceptor() {
                    
                    /**
                    * Object o:被代理的对象
                    * Method method:被拦截的方法
                    * Object[] objects:被拦截的方法的参数们
                    * MethodProxy methodProxy:MethodProxy类型的被拦截方法
                    **/
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        
                        ma.before();
        
                        Object obj = method.invoke(us, objects);
        
                        ma.after();
        
                        return obj;
                    }
                });
        
                //  4.  通过eh对象的create()方法来得到指定的对象
                IUserService<Object> ius = (IUserService<Object>) eh.create();
        
                return ius;
            }
        }
        

jdk代理方式与cglib代理方式的区别

  1. JDK代理只能对实现了接口的类生成代理,而CGLIB是通过继承的方式实现代理也可以为实现了接口的类强制使用
  2. JDK代理在使用次数较少时效率高于CGLIB代理,当大量使用时CGLIB代理更胜一筹.但随着jdk版本的升级,JDK代理效率不断提升,到jdk8时高于CGLIB代理

spring框架中的动态代理方式

  1. 创建被代理类接口并实现接口

  2. 创建代理类,并实现MethodInterceptor接口

    • 重写invoke方法

    •  @Override
          public Object invoke(MethodInvocation invocation) throws Throwable {
        
              before();
        
              //  业务处理方法的调用
              Object obj = invocation.proceed();
        
              after();
        
              return obj;
          }
      
  3. 配置beans.xml

    • 分别配置被代理类bean(id="us")和代理类bean(id="my")

    • 配置代理工厂

      • <!--
                ProxyFactoryBean代理的FactoryBean对象,我们现在要代理的是us
                    包含四个属性注入:
                        1.  interfaces: 接口对象们
                            <list>
                                <value>com.qfedu.aop03.IUserService</value>
                                <value>com.qfedu.aop03.IUserService</value>
                                <value>com.qfedu.aop03.IUserService</value>
                            </list>
                        2.  target:目标对象,哪个对象将被以代理的方式创建
                        3.  interceptorNames:拦截对象的名称,自定义的MethodInterceptor对象,注意它的包结构组成
                        4.  optimize:boolean类型的值:
                                true:强制使用cglib的动态代理方式
                                false:使用jdk自带的动态代理
                                cglib:code generation library,代码生成库,性能更高
            -->
            <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
                <property name="interfaces" value="com.qfedu.aop03.IUserService" />
                <property name="target" ref="us" />
                <property name="interceptorNames" value="my" />
                <property name="optimize" value="true" />
            </bean>
        
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容