7.AOP之JDK动态代理

1.简介
基于接口的动态代理技术,利用拦截器(必须实现invocationHandler)和反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来实现方法增强。
在这里插入图片描述

2.生成代理对象
在项目目录“/src/main/java/com/steven”下新建proxy目录,并在proxy目录下新建JDKProxyFactory类,在类中提供一个创建JDK代理对象的方法createJDKProxyObject,具体代码如下。

public class JDKProxyFactory {
    @Autowired
    private IAccountService accountService;

    @Autowired
    private TransactionManager transactionManager;

    public IAccountService createJDKProxyObject() {
        /**
         * 采用JDK动态代理技术生成目标类的代理对象
         * classLoader 类加载器,借助被代理类对象获取类加载器
         * interface 代理对象所需实现的全部接口,借助被代理类对象获取所需实现的全部接口
         * invocationHandler 当代理对象调用接口中的任意方法时,都会执行InvocationHandler中invoke方法
         */
        IAccountService accountServiceProxy = (IAccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {
            /**
             * @param proxy 代理对象引用
             * @param method 被代理对象方法引用
             * @param args 被代理对象方法入参
             */
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                try {
                    //手动开启事务
                    transactionManager.beginTransaction();

                    System.out.println("被代理类对象方法将要被执行");
                    //让被代理对象的原方法执行
                    method.invoke(accountService, args);
                    System.out.println("被代理类对象方法已经被执行");

                    //手动提交事务
                    transactionManager.commit();
                } catch (Exception e) {
                    e.printStackTrace();
                    //手动回滚事务
                    transactionManager.rollback();
                } finally {
                    //手动释放资源
                    transactionManager.release();
                }
                return null;
            }
        });
        return accountServiceProxy;
    }
}

3.修改业务层代码
在转账工程基础上,删除业务层的事务控制代码,具体代码如下。

@Service
public class AccountServiceImpl implements IAccountService {
    @Autowired
    private IAccountDao accountDao;

    public void transfer(String outUser, String inUser, Double money) {
        accountDao.out(outUser, money);

        int i = 1 / 0;

        accountDao.in(inUser, money);
    }
}

4.将JDKProxyFactory交给Spring容器管理
在applicationContext.xml文件中添加如下bean标签。

<bean id="jdkProxyFactory" class="com.steven.proxy.JDKProxyFactory"/>

5.编写测试类

public class Test {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        JDKProxyFactory jdkProxyFactory = (JDKProxyFactory) context.getBean("jdkProxyFactory");
        IAccountService accountService = jdkProxyFactory.createAccountServiceJDKProxy();
        accountService.transfer("steven", "sherry", 100d);
    }
}

程序执行成功,查看数据库数据,steven和sherry的10000元数额未发生变化。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值