Java三种代理模式(Spring动态代理对象)

目录结构:

在这里插入图片描述

以下这段代码,复制其他博客,链接在下方
----------------------------------------------------------------

代理模式

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法

举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)来解决.这就是代理思想在现实中的一个例子
1.静态代理(类似于装饰者模式)
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.

下面举个案例来解释:
模拟保存动作,定义一个保存动作的接口:IUserDao.java,然后目标对象实现这个接口的方法UserDao.java,此时如果使用静态代理方 式,就需要在代理对象(UserDaoProxy.java)中也实现IUserDao接口.调用的时候通过调用代理对象的方法来调用目标对象.
需要注意的是,代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法
代码示例:
接口:IUserDao.java

/**
 * 接口
 */
public interface IUserDao {

    void save();
}

目标对象:UserDao.java

/**
 * 接口实现
 * 目标对象
 */
public class UserDao implements IUserDao {
    public void save() {
        System.out.println("----已经保存数据!----");
    }
}

代理对象:UserDaoProxy.java

/**
 * 代理对象,静态代理
 */
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("提交事务...");
    }
}

测试类:App.java

/**
 * 测试类
 */
public class App {
    public static void main(String[] args) {
        //目标对象
        UserDao target = new UserDao();

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

        proxy.save();//执行的是代理的方法
    }
}

静态代理总结:
1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
2.缺点:

因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
如何解决静态代理中的缺点呢?答案是可以使用动态代理方式

扫描二维码关注公众号,回复: 8884821 查看本文章

以上这段代码,复制其他博客,链接在下方

2.观光代码=>动态代理

UserService.java

package com.eilas.service;

public interface UserService {
    void save();
    void delete();
    void update();
    void find();
}

UserServiceImpl.java

package com.eilas.service;

public class UserServiceImpl implements UserService{
    @Override
    public void save() {
        System.out.println("保存用户!");
        //int i = 1/0;
    }
    @Override
    public void delete() {
        System.out.println("删除用户!");
    }
    @Override
    public void update() {
        System.out.println("更新用户!");
    }
    @Override
    public void find() {
        System.out.println("查找用户!");
    }
}

UserServiceProcyFactory.java(错别字母)

package com.eilas.c_proxy;

import com.eilas.service.UserService;
import com.eilas.service.UserServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class UserServiceProcyFactory implements InvocationHandler {

    public UserServiceProcyFactory(UserService us) {
        super();
        this.us = us;
    }
    private UserService us;

    public UserService getUserServiceProxy(){
        UserService usProxy = (UserService) Proxy.newProxyInstance(UserServiceProcyFactory.class.getClassLoader(),
                UserServiceImpl.class.getInterfaces(),
                this);
        return usProxy;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("open");
        Object invoke = method.invoke(us,args);
        System.out.println("commit");

        return invoke;
    }
}

Proxy_Test.java

package com.eilas.c_proxy;

import com.eilas.service.UserService;
import com.eilas.service.UserServiceImpl;
import org.junit.Test;

public class Proxy_Test {
    @Test
    public void fun1() {
        UserService userService = new UserServiceImpl();
        UserServiceProcyFactory factory = new UserServiceProcyFactory(userService);
        UserService usProxy = factory.getUserServiceProxy();
        usProxy.save();
        //代理对象与被代理对象实现了相同的  -->接口**
        //代理对象 与 被代理对象没有继承关系
        System.out.println(usProxy instanceof UserServiceImpl );//false
    }

}

result:

open
保存用户!
commit

3.观光代码=>cglib代理

cglib.jar在spring-core中整合了,所以不用导入该包

UserServiceProxyFactory2.java

package com.eilas.c_proxy;

import com.eilas.service.UserService;
import com.eilas.service.UserServiceImpl;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class UserServiceProxyFactory2 implements MethodInterceptor {
    public UserService getUserServiceProxy() {

        Enhancer en = new Enhancer(); //帮我们生成代理对象

        en.setSuperclass(UserServiceImpl.class); //设置对谁进行代理

        en.setCallback(this); //代理要做什么

        UserService us = (UserService) en.create(); //创建代理对象

        return us;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //打开事务
        System.out.println("打开事务!");
        //调用原有方法
        Object returnValue = methodProxy.invokeSuper(o, objects);
        //提交事务
        System.out.println("提交事务!");

        return returnValue;
    }
}

Proxy_Test.java

package com.eilas.c_proxy;

import com.eilas.service.UserService;
import com.eilas.service.UserServiceImpl;
import org.junit.Test;

public class Proxy_Test {
    @Test
    public void fun1() {
        UserService userService = new UserServiceImpl();
        UserServiceProcyFactory factory = new UserServiceProcyFactory(userService);
        UserService usProxy = factory.getUserServiceProxy();
        usProxy.save();
        //代理对象与被代理对象实现了相同的  -->接口**
        //代理对象 与 被代理对象没有继承关系
        System.out.println(usProxy instanceof UserServiceImpl );//false
    }

    @Test
    public void fun2() {
        UserServiceProxyFactory2 factory2 = new UserServiceProxyFactory2();
        UserService usProxy = factory2.getUserServiceProxy();
        usProxy.save();

        //判断代理对象是否属于被代理对象类型  
        //代理对象继承了被代理对象=>true --->继承***
        System.out.println(usProxy instanceof UserServiceImpl);//true

    }
}


result:

打开事务!
保存用户!
提交事务!

Java的三种代理模式(Spring动态代理对象)
Java 编程 ,事务管理的作用

发布了25 篇原创文章 · 获赞 5 · 访问量 1147

猜你喜欢

转载自blog.csdn.net/tinfengyee/article/details/88845442