spring的代理模式怎么实现

worktile 其他 44

回复

共3条回复 我来回复
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    Spring框架中的代理模式主要有两种实现方式:JDK动态代理和CGLib动态代理。

    1. JDK动态代理:JDK动态代理是通过反射机制来实现的,要实现JDK动态代理,需要满足两个条件:目标类必须实现接口,且目标类的方法必须是接口中定义的方法。下面是实现JDK动态代理的步骤:

      1.1 定义接口:定义一个接口,该接口是目标类的接口。

      1.2 目标类实现接口:编写一个目标类,实现定义的接口。

      1.3 实现InvocationHandler接口:编写一个实现InvocationHandler接口的类,该类实现invoke方法,在invoke方法中通过反射调用目标类的方法。

      1.4 通过Proxy类创建代理对象:使用Proxy类的newProxyInstance方法,创建一个代理对象。该方法需要三个参数:ClassLoader,用于加载代理类;Class[],指定代理类实现的接口;InvocationHandler,用于实现代理对象的方法逻辑。

    2. CGLib动态代理:CGLib动态代理是通过生成子类来实现的,对于没有实现接口的类,可以使用CGLib动态代理。下面是实现CGLib动态代理的步骤:

      2.1 引入CGLib库:在项目中引入CGLib库。

      2.2 创建Enhancer对象:通过Enhancer类的create方法创建Enhancer对象。

      2.3 设置父类和回调函数:通过setSuperclass方法设置目标类作为父类,通过setCallback方法设置回调函数,回调函数通过实现MethodInterceptor接口重写intercept方法来实现。

      2.4 创建代理对象:调用Enhancer对象的create方法创建代理对象。

    总结:Spring框架中的代理模式主要有JDK动态代理和CGLib动态代理两种实现方式。其中,JDK动态代理要求目标类实现接口,通过反射机制在InvocationHandler类中调用目标类的方法;而CGLib动态代理则通过生成子类来实现代理。

    1年前 0条评论
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    Spring框架提供了多种方式实现代理模式,以下是其中几种常用的实现方式:

    1. JDK动态代理:实现了被代理对象所实现的接口,并通过动态生成代理类,在运行时生成代理对象。该方式需要使用到Java的反射机制,只能代理实现了接口的类。
    public interface UserDao {
        void save();
    }
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() {
            System.out.println("保存用户信息。");
        }
    }
    
    public class UserDaoProxy implements InvocationHandler {
        private Object target;
    
        public Object bind(Object target){
            this.target = target;
            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;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            UserDao userDao = (UserDao) new UserDaoProxy().bind(new UserDaoImpl());
            userDao.save();
        }
    }
    
    1. CGLib动态代理:通过继承被代理对象,生成相应的子类代理对象。该方式无需实现接口,直接代理实现类。
    public class UserDao {
        public void save() {
            System.out.println("保存用户信息。");
        }
    }
    
    public class UserDaoInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("开启事务。");
            Object result = method.invoke(obj, args);
            System.out.println("提交事务。");
            return result;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(UserDao.class);
            enhancer.setCallback(new UserDaoInterceptor());
    
            UserDao userDao = (UserDao) enhancer.create();
            userDao.save();
        }
    }
    
    1. 静态代理:创建一个代理类,持有被代理对象的引用,并在调用被代理对象的方法前后进行额外的操作。
    public interface UserDao {
        void save();
    }
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() {
            System.out.println("保存用户信息。");
        }
    }
    
    public class UserDaoProxy implements UserDao {
        private UserDao target;
    
        public UserDaoProxy(UserDao target) {
            this.target = target;
        }
    
        @Override
        public void save() {
            System.out.println("开启事务。");
            target.save();
            System.out.println("提交事务。");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            UserDao userDao = new UserDaoImpl();
            UserDao userDaoProxy = new UserDaoProxy(userDao);
            userDaoProxy.save();
        }
    }
    
    1. Spring AOP:Spring框架通过AOP(面向切面编程)提供了更为方便的代理模式实现方式。使用Spring AOP可以在不修改原始类的情况下,通过配置切面和通知将额外的操作织入到目标方法中。
    public interface UserDao {
        void save();
    }
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() {
            System.out.println("保存用户信息。");
        }
    }
    
    public class LogAdvice implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("开启事务。");
            Object result = invocation.proceed();
            System.out.println("提交事务。");
            return result;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserDao userDao = (UserDao) context.getBean("userDao");
            userDao.save();
        }
    }
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="userDao" class="com.example.UserDaoImpl">
            <property name="proxyTargetClass" value="true"/>
        </bean>
    
        <bean id="logAdvice" class="com.example.LogAdvice"/>
    
        <aop:aspectj-autoproxy proxy-target-class="true">
            <aop:aspect ref="logAdvice">
                <aop:around method="invoke" pointcut="execution(* com.example.UserDao.save(..))"/>
            </aop:aspect>
        </aop:aspectj-autoproxy>
    
    </beans>
    

    以上是几种常用的实现代理模式的方式,根据具体需求选择合适的方式。需要注意的是,动态代理方式适用于对目标类的所有方法做代理,而静态代理和Spring AOP可以根据需要选择性地对某些方法进行代理。

    1年前 0条评论
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    Spring框架提供了两种实现代理模式的方式,即JDK动态代理和CGLIB动态代理。下面将分别介绍这两种实现方式的使用方法和操作流程。

    1. JDK动态代理

    JDK动态代理是通过Java的反射机制来实现的,它要求被代理的类必须实现一个接口。

    (1)定义接口
    首先需要定义一个接口,该接口包含需要被代理的方法。

    (2)创建被代理类
    创建一个被代理类,该类实现接口中定义的方法。

    (3)创建代理类
    创建一个代理类,该类实现InvocationHandler接口,并重写其invoke方法。在invoke方法中可以实现对被代理对象的方法进行增强或处理。

    (4)创建代理对象
    使用Proxy类的newProxyInstance方法创建代理对象。

    (5)调用被代理对象的方法
    通过代理对象来调用被代理对象的方法。

    1. CGLIB动态代理

    CGLIB(Code Generation Library)是一个用于生成Java字节码的库,它可以在运行时动态地生成子类来扩展被代理类的功能,而不需要被代理类实现任何接口。

    (1)引入CGLIB库
    首先需要引入CGLIB库的依赖,可以在项目的pom.xml文件中添加相关依赖。

    (2)创建被代理类
    创建一个被代理类,该类不需要实现任何接口。

    (3)创建代理类
    创建一个代理类,该类需要继承被代理类,并重写其方法。在重写的方法中可以实现对被代理对象的方法进行增强或处理。

    (4)创建代理对象
    使用Enhancer类的create方法创建代理对象。

    (5)调用被代理对象的方法
    通过代理对象来调用被代理对象的方法。

    总结:JDK动态代理适用于那些实现了接口的类,而CGLIB动态代理适用于那些没有实现接口的类。在实际应用中,可以根据具体情况选择使用其中一种代理方式来实现需求。

    1年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部