spring的代理模式怎么实现
-
Spring框架中的代理模式主要有两种实现方式:JDK动态代理和CGLib动态代理。
-
JDK动态代理:JDK动态代理是通过反射机制来实现的,要实现JDK动态代理,需要满足两个条件:目标类必须实现接口,且目标类的方法必须是接口中定义的方法。下面是实现JDK动态代理的步骤:
1.1 定义接口:定义一个接口,该接口是目标类的接口。
1.2 目标类实现接口:编写一个目标类,实现定义的接口。
1.3 实现InvocationHandler接口:编写一个实现InvocationHandler接口的类,该类实现invoke方法,在invoke方法中通过反射调用目标类的方法。
1.4 通过Proxy类创建代理对象:使用Proxy类的newProxyInstance方法,创建一个代理对象。该方法需要三个参数:ClassLoader,用于加载代理类;Class[],指定代理类实现的接口;InvocationHandler,用于实现代理对象的方法逻辑。
-
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年前 -
-
Spring框架提供了多种方式实现代理模式,以下是其中几种常用的实现方式:
- 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(); } }- 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(); } }- 静态代理:创建一个代理类,持有被代理对象的引用,并在调用被代理对象的方法前后进行额外的操作。
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(); } }- 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年前 -
Spring框架提供了两种实现代理模式的方式,即JDK动态代理和CGLIB动态代理。下面将分别介绍这两种实现方式的使用方法和操作流程。
- JDK动态代理
JDK动态代理是通过Java的反射机制来实现的,它要求被代理的类必须实现一个接口。
(1)定义接口
首先需要定义一个接口,该接口包含需要被代理的方法。(2)创建被代理类
创建一个被代理类,该类实现接口中定义的方法。(3)创建代理类
创建一个代理类,该类实现InvocationHandler接口,并重写其invoke方法。在invoke方法中可以实现对被代理对象的方法进行增强或处理。(4)创建代理对象
使用Proxy类的newProxyInstance方法创建代理对象。(5)调用被代理对象的方法
通过代理对象来调用被代理对象的方法。- CGLIB动态代理
CGLIB(Code Generation Library)是一个用于生成Java字节码的库,它可以在运行时动态地生成子类来扩展被代理类的功能,而不需要被代理类实现任何接口。
(1)引入CGLIB库
首先需要引入CGLIB库的依赖,可以在项目的pom.xml文件中添加相关依赖。(2)创建被代理类
创建一个被代理类,该类不需要实现任何接口。(3)创建代理类
创建一个代理类,该类需要继承被代理类,并重写其方法。在重写的方法中可以实现对被代理对象的方法进行增强或处理。(4)创建代理对象
使用Enhancer类的create方法创建代理对象。(5)调用被代理对象的方法
通过代理对象来调用被代理对象的方法。总结:JDK动态代理适用于那些实现了接口的类,而CGLIB动态代理适用于那些没有实现接口的类。在实际应用中,可以根据具体情况选择使用其中一种代理方式来实现需求。
1年前