zoukankan      html  css  js  c++  java
  • 代理实现aop以及代理工厂实现增强

    一、静态代理实现

      1.接口(抽象主题)

      

       2.接口的实现类(真实主题)

      

      3.代理类(代理主题)

      

      4.测试类:

         ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
            ProxySubject proxySubject =(ProxySubject) context.getBean("proxySubject");
            proxySubject.doSome();

    二、JDK动态代理

      JDK动态代理所用到的代理类在程序调用到代理类对象时才由JVM真正创建,JVM根据传进来的 业务实现类对象 以及 方法名 ,动态地创建了一个代理类的class文件并被字节码引擎执行,然后通过该代理类对象进行方法调用。

       1.抽象主题,真实主题与上面一致

       2.动态代理类

     
    package com.cmy.handler;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class DoSomeBeanFactory implements InvocationHandler {
        private Object target;//这其实业务实现类对象,用来调用具体的业务方法
    
        public Object bind(Object target) {
            this.target = target;  //接收业务实现类对象参数
    
            //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
            //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), this);
        }
    
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("前置=====");
            //调用真正的业务方法
            Object result = method.invoke(target, args);
            System.out.println("后置=====");
            return result;
        }
    }
     

      3.测试类

     
    public class ProxyDemo {
        public static void main(String[] args) {
             //创建业务类对象
             Subject subject=new ReallySubject();
             //创建代理对象
             DoSomeBeanFactory factory=new DoSomeBeanFactory();
             //调用bind方法获取代理对象
             Subject proxy = (Subject)factory.bind(subject);
             //调用目标函数
             proxy.say();
        } 
    }
     

    三、Cglib动态代理

       cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。

      新建代理类

    package com.cmy.handler;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    import java.lang.reflect.Method;
    
    public class DoSomeBeanCGlib implements MethodInterceptor{
        private Object target;//业务类对象,供代理方法中进行真正的业务方法调用
    
        //相当于JDK动态代理中的绑定
        public Object getInstance(Object target) {
            this.target = target;  //给业务对象赋值
            Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
            enhancer.setSuperclass(this.target.getClass());  //为加强器指
    
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实    现intercept()方法进行拦
            enhancer.setCallback(this);
            // 创建动态代理类对象并返回
            return enhancer.create();
        }
    
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("预处理——————");
            methodProxy.invokeSuper(o, objects); //调用业务类(父类中)的方法
            System.out.println("调用后操作——————");
            return null;
        }
    }
     

     四.代理工厂增强

     借助Spring IOC的机制,为ProxyFactory代理工厂的属性实现依赖注入,这样做的优点是可配置型高,易用性好。

    1.创建抽象主题

    public interface ProService {
        public void doSome();
    }

    2.创建真实主题

     
    public class ProServiceImpl implements  ProService {
        @Override
        public void doSome() {
            System.out.println("123");
        }
    }
     

    3.创建增强类

      这里实现了前置增强的接口,用前置增强来模拟增强

     
    import org.springframework.aop.MethodBeforeAdvice;
    
    import java.lang.reflect.Method;
    
    public class BeaforeProxy implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] objects, Object o) throws Throwable {
            System.out.println("前置");
        }
    }
     

    4.配置大配置文件

     
     <!--注入bean-->
        <bean id="proService" class="cn.spring.proxyFactory.ProServiceImpl"></bean>
        <!--切面-->
        <bean id="beaforeProxy" class="cn.spring.proxyFactory.BeaforeProxy"></bean>
        <!--代理工厂实现增强-->
        <bean id="ProFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!--将增强和业务织入到一起-->
            <property name="target" ref="proService"></property>
            <!--拦截增强类-->
            <property name="interceptorNames" value="beaforeProxy"></property>
        </bean>
     

    5.测试

     public static void main(String[] args) {
            ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
            ProService proService =(ProService) context.getBean("ProFactory");
            proService.doSome();
        }

    6.结果

      值得注意的是这种代理工场的代理方式默认为Jdk,如果不存在接口,则使用Cglib代理,这个可以通过断点直观看出,若想规定使用,则可以在大配置文件代理工厂的节点下中设置

    <!--更换代理方式   默认值为false  jdk动态代理,当没有接口时,自动改成cglib-->
            <property name="proxyTargetClass" value="true"></property>

  • 相关阅读:
    Wannafly挑战赛29-A/B
    hdu-4819-线段树套线段树
    CF-877E-线段树+哈希
    CF-413E-线段树
    CF-787D-线段树建图+最短路
    CF-339D-线段树
    2017.4.26 慕课网--Java 高并发秒杀API配置文件(持续更新)
    2017.4.26 慕课网--Java 高并发秒杀API(一)
    2017.4.19 慕课网-通过自动回复机器人学习mybatis
    2017.4.18 linux中执行某文件提示权限不够
  • 原文地址:https://www.cnblogs.com/danxun/p/11777023.html
Copyright © 2011-2022 走看看