Spring JDK 动态代理

谁借莪1个温暖的怀抱¢ 2022-04-14 04:13 308阅读 0赞

一.动态代理(需要定义接口)
动态代理类是在程序运行期间由JVM通过反射等机制动态的生成的,所以不存在代理类的字节码文件。
代理对象和真实对象的关系是在程序运行事情才确定的。
JDK动态代理API分析:
1、java.lang.reflect.Proxy 类:
Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
主要方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler hanlder)
方法职责:为指定类加载器、一组接口及调用处理器生成动态代理类实例
参数:
loader :类加载器778776
interfaces :模拟的接口
hanlder :代理执行处理器
返回:动态生成的代理对象

2、java.lang.reflect.InvocationHandler接口:
public Object invoke(Object proxy, Method method, Object[] args)
方法职责:负责集中处理动态代理类上的所有方法调用
参数:
proxy :生成的代理对象
method :当前调用的真实方法对象
args :当前调用方法的实参
返回: 真实方法的返回结果

3.JDK动态代理操作步骤
① 实现InvocationHandler接口,创建自己增强代码的处理器。
② 给Proxy类提供ClassLoader对象和代理接口类型数组,创建动态代理对象。

二.JDK动态代理需要注意的几点:
JDK动态代理:
1,代理的对象必须要实现一个接口;
2,需要为每个对象创建代理对象;
3,动态代理的最小单位是类(所有类中的方法都会被处理);

三.JDK动态代理拓展及其常用的方法:
1,JAVA动态代理是使用java.lang.reflect包中的Proxy类与InvocationHandler接口这两个来完成的。
2,要使用JDK动态代理,必须要定义接口。
3,JDK动态代理将会拦截所有pubic的方法(因为只能调用接口中定义的方法),这样即使在接口中增加了新的方法,不用修改代码也会被拦截。
4,如果只想拦截一部分方法,可以在invoke方法中对要执行的方法名进行判断

四.JDK动态代理代码示例

接口及其实现类

  1. public interface IEmployeeService {
  2. void save(Employee e);
  3. void update(Employee e);
  4. }
  5. @Service("target")
  6. public class EmployeeServiceImpl implements IEmployeeService{
  7. @Autowired
  8. private IEmployeeDao employeeDao ;
  9. @Override
  10. public void save(Employee e) {
  11. employeeDao.save(e);
  12. }
  13. @Override
  14. public void update(Employee e) {
  15. employeeDao.update(e);
  16. }
  17. }

事物管理器示例

  1. @Component("txManager")
  2. public class TransactionManager {
  3. public void begin(){
  4. System.out.println("事物开启。。。。。");
  5. }
  6. public void commit(){
  7. System.out.println("事物提交。。。。。");
  8. }
  9. public void rollback(){
  10. System.out.println("事物回滚。。。。。");
  11. }
  12. }

JDK动态代理类(通用)

  1. @Component("jdkProxy")
  2. public class TransactionManagerHandler implements java.lang.reflect.InvocationHandler {
  3. @Autowired
  4. @Qualifier("target")
  5. private Object target; //真实对象(被代理的对象):在此处指的是EmployeeServiceImpl
  6. @Autowired
  7. private TransactionManager txManager;
  8. // 创建一个代理对象
  9. public <T>T getProxyObject(){
  10. Object obj = Proxy.newProxyInstance(target.getClass().getClassLoader(), //类加载器
  11. target.getClass().getInterfaces(), // 真实对象实现的接口:EmployeeServiceImpl的接口
  12. this); // 增强的对象
  13. return (T)obj;
  14. }
  15. // 在真实对象上做增强操作
  16. @Override
  17. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  18. Object obj = null;
  19. txManager.begin();
  20. try {
  21. obj = method.invoke(target, args); // 真实对象中的方法
  22. txManager.commit();
  23. } catch (Exception e) {
  24. txManager.rollback();
  25. e.printStackTrace();
  26. }
  27. return obj;
  28. }
  29. }

配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context.xsd
  11. ">
  12. <!-- 解析autowired,resource,qualifier-->
  13. <context:annotation-config />
  14. <!--去哪些包下面去扫描组件-->
  15. <context:component-scan base-package="com.shenzhenair.day02.common" />
  16. <context:component-scan base-package="com.shenzhenair.day02.jdk_proxy" />
  17. </beans>

测试类

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration("classpath:com/shenzhenair/day02/jdk_proxy/jdkProxy.xml")
  3. public class JDKProxyTest {
  4. @Autowired
  5. @Qualifier("jdkProxy")
  6. private TransactionManagerHandler handler;
  7. //com.sun.proxy.$Proxy15
  8. @Test
  9. public void testSave(){
  10. // 获得代理对象
  11. IEmployeeService proxyObject = handler.getProxyObject();
  12. System.out.println(proxyObject.getClass());
  13. proxyObject.save(new Employee());
  14. }
  15. }

运行结果

20181124111259948.png

发表评论

表情:
评论列表 (有 0 条评论,308人围观)

还没有评论,来说两句吧...

相关阅读

    相关 9_Spring_JDK动态代理

    代理模式 是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。 房产中介代替业主卖房 ![b9c7284a183c4a6