代理实现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>

原文地址:https://www.cnblogs.com/danxun/p/11777023.html