您的位置:首页 > 编程语言 > Java开发

java的三种代理模式和spring aop介绍

2017-09-23 17:35 573 查看
代理模式:通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能

1.静态代理

定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类

示例

/**

 * 接口

 */

public interface IUserDao {

    void save();

}

/**

 * 接口实现

 * 目标对象

 */

public class UserDao implements IUserDao {

    public void save() {

        System.out.println("----已经保存数据!----");

    }

}

/**

 * 代理对象,静态代理

 */

public class UserDaoProxy implements IUserDao{

    //接收保存目标对象

    private IUserDao target;

    public UserDaoProxy(IUserDao target){

        this.target=target;

    }

    public void save() {

        System.out.println("开始事务...");

        target.save();//执行目标对象的方法

        System.out.println("提交事务...");

    }

}

/**

 * 测试类

 */

public class App {

    public static void main(String[] args) {

        //目标对象

        UserDao target = new UserDao();
//代理对象,把目标对象传给代理对象,建立代理关系

        UserDaoProxy proxy = new UserDaoProxy(target);
proxy.save();//执行的是代理的方法

    }

}

静态代理总结

1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.

2.缺点:

因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
2.动态代理也叫jdk代理,可以不实现接口但是要指定接口类型

所在包

代理类所在包:java.lang.reflect.Proxy

JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

ClassLoader
loader,
:指定当前目标对象使用类加载器,获取加载器的方法是固定的
Class<?>[]
interfaces,
:目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler
h
:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入

示例:两种写法,第一种比较好理解点

第一种

package thread;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Proxy;

import java.lang.reflect.Method;

/**

 * 创建动态代理对象

 * 动态代理不需要实现接口,但是需要指定接口类型

 */

public class ProxyFactory2 implements InvocationHandler{

    //维护一个目标对象

    private Object target;

    public ProxyFactory2(Object target){

        this.target=target;

    }
public Object invoke(Object proxy, Class<?>[], Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("开始事务2");
method.invoke(target, args);
System.out.println("提交事务2");
return null;
}
public <T> T getProxy()
{
System.out.println("target.getClass().getClassLoader()--"+target.getClass().getClassLoader());
System.out.println("target.getClass().getInterfaces()--"+target.getClass().getInterfaces());
return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}

}

/**
 * 测试类
 */
public class App {
    public static void main(String[] args) {
        // 目标对象
        IUserDao target = new UserDao();
        // 【原始的类型 class cn.itcast.b_dynamic.UserDao】
        System.out.println(target.getClass());

        // 给目标对象,创建代理对象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
        // class $Proxy0   内存中动态生成的代理对象
        System.out.println(proxy.getClass());

        // 执行方法   【代理对象】
        proxy.save();
    }
}

}

第二种

/**

 * 创建动态代理对象

 * 动态代理不需要实现接口,但是需要指定接口类型

 */

public class ProxyFactory{

    //维护一个目标对象

    private Object target;

    public ProxyFactory(Object target){

        this.target=target;

    }

   //给目标对象生成代理对象

    public Object getProxyInstance(){

        return Proxy.newProxyInstance(

                target.getClass().getClassLoader(),

                target.getClass().getInterfaces(),

                new InvocationHandler() {

                    @Override

                    public Object invoke(Object proxy, Class<?>[], Object[] args) throws Throwable {

                        System.out.println("开始事务2");

                        //执行目标对象方法

                        Object returnValue = method.invoke(target, args);

                        System.out.println("提交事务2");

                        return returnValue;

                    }

                }

        );

    }
/**
 * 测试类
 */
public class App {
    public static void main(String[] args) {
        // 目标对象
        IUserDao target = new UserDao();
        // 【原始的类型 class cn.itcast.b_dynamic.UserDao】
        System.out.println(target.getClass());

        // 给目标对象,创建代理对象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
        // class $Proxy0   内存中动态生成的代理对象
        System.out.println(proxy.getClass());

        // 执行方法   【代理对象】
        proxy.save();
    }
}

}

静态代理和动态代理的区别以及静态代理和动态代理的不足

静态代理的不足

1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜

      任了。 
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度

静态代理和动态代理的区别:

静态代理由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了;动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定;

动态代理的优缺点:

动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。

同静态代理一样要求目标对象实现某个接口,比如例子中的UserDao必须要实现IUserDao接口,否则不能使用,但是往往目标对象并没有实现某个接口,如果使用Cglib代理则无需目标对象必须实现接口

3.Cglib,无需目标类实现任何接口。被一些AOP框架使用,比如Spring.Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理

/**
* 目标对象,没有实现任何接口
*/

public class UserDao {
public void save() {
        System.out.println("----已经保存数据!----");
    }

}

/**
* Cglib子类代理工厂
* 对UserDao在内存中动态构建一个子类对象
*/
public class ProxyFactory implements MethodInterceptor{
    //维护目标对象
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    //给目标对象创建一个代理对象
    public Object getProxyInstance(){
        //1.工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(target.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();

    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开始事务...");

        //执行目标对象的方法
        Object returnValue = method.invoke(target, args);

        System.out.println("提交事务...");

        return returnValue;
    }
}

/**
* Cglib子类代理工厂
* 对UserDao在内存中动态构建一个子类对象
*/
public class ProxyFactory implements MethodInterceptor{
    //维护目标对象
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    //给目标对象创建一个代理对象
    public Object getProxyInstance(){
        //1.工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(target.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();

    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开始事务...");

        //执行目标对象的方法
        Object returnValue = method.invoke(target, args);

        System.out.println("提交事务...");

        return returnValue;
    }
}

参考文章:http://www.cnblogs.com/cenyu/p/6289209.html

4.spring aop


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: