Spring JDK 动态代理

一.动态代理(需要定义接口)
  动态代理类是在程序运行期间由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动态代理代码示例

  接口及其实现类

public interface IEmployeeService {
    void save(Employee e);
    void update(Employee e);
}
@Service("target")
public class  EmployeeServiceImpl  implements IEmployeeService{
     @Autowired
     private IEmployeeDao employeeDao ;
    @Override
    public void save(Employee e) {
        employeeDao.save(e);
    }
    @Override
    public void update(Employee e) {
        employeeDao.update(e);
    }
}

事物管理器示例

@Component("txManager")
public class TransactionManager {
    public  void  begin(){
        System.out.println("事物开启。。。。。");
    }
    public  void  commit(){
        System.out.println("事物提交。。。。。");
    }
    public  void  rollback(){
        System.out.println("事物回滚。。。。。");
    }
}

 JDK动态代理类(通用)

@Component("jdkProxy")
public class TransactionManagerHandler implements  java.lang.reflect.InvocationHandler {
    @Autowired
    @Qualifier("target")
    private Object target; //真实对象(被代理的对象):在此处指的是EmployeeServiceImpl
    @Autowired
    private TransactionManager txManager;

    // 创建一个代理对象
    public <T>T getProxyObject(){
       Object obj = Proxy.newProxyInstance(target.getClass().getClassLoader(), //类加载器
                target.getClass().getInterfaces(), // 真实对象实现的接口:EmployeeServiceImpl的接口
                this); // 增强的对象
        return (T)obj;
    }

    // 在真实对象上做增强操作
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object obj = null;
        txManager.begin();
        try {
            obj = method.invoke(target, args); // 真实对象中的方法
            txManager.commit();
        } catch (Exception e) {
            txManager.rollback();
            e.printStackTrace();
        }

        return obj;
    }
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        ">

    <!-- 解析autowired,resource,qualifier-->
    <context:annotation-config />
    <!--去哪些包下面去扫描组件-->
    <context:component-scan base-package="com.shenzhenair.day02.common" />
    <context:component-scan base-package="com.shenzhenair.day02.jdk_proxy" />


</beans>

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:com/shenzhenair/day02/jdk_proxy/jdkProxy.xml")
public class JDKProxyTest {
    @Autowired
    @Qualifier("jdkProxy")
    private TransactionManagerHandler handler;

     //com.sun.proxy.$Proxy15
    @Test
    public void testSave(){
        // 获得代理对象
        IEmployeeService  proxyObject = handler.getProxyObject();
        System.out.println(proxyObject.getClass());
        proxyObject.save(new Employee());
    }
}

运行结果

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值