必威体育Betway必威体育官网
当前位置:首页 > IT技术

Spring框架——自动代理

时间:2019-10-23 19:14:24来源:IT技术作者:seo实验室小编阅读:72次「手机版」
 

代理超人

Spring框架中的面向切面思想在实现的过程中,核心的技术就是动态代理

目的:

在实际开发中,通常为目标类的所有业务方法附加通用性的增强功能,比如日志功能、事务处理等。最简单的方式,将表示增强功能的代码直接添加到业务方法中。

将表示增强功能的代码直接添加到业务方法中被称为:代码侵入

增强代码侵入业务代码所产生的问题:

(1)业务方法的核心功能不突出;

(2)增强代码与业务代码耦合在一起,不利于日后的维护

如何改进呢:

使用代理模式将增强代码与业务代码分离。

静态代理传送:

设计模式(十八)——代理模式

动态代理

首先看看静态代理的不足:

静态代理类的每个代理方法中,含有相同的增强代码,比如含有时间点记录的代码

如果目标对象含有很多的业务方法,比如几十个业务方法,会造成代理方法中含有大量的相同代码,产生代码冗余。

动态代理用到Invocationhandler接口

InvocationHandler接口中只有一个invoke方法,即

Object invoke(Object proxy, Method method, Object[] args)

invoke方法的作用,以反射的方式将代理方法的调用解析为统一的形式:

  invoke(proxy,method, null);

在代理方法中,以反射的方式,通过调用InvocationHanler对象的invoke方法,实现代理方法的调用委派。

如何让JVM动态创建代理对象呢?

需要使用javaSE JDK中的Proxy类。

Proxy类位于java.lang.reflect包下,是JVM所创建的动态代理类的父类。

Proxy类提供了如下的静态方法,用于通知JVM执行时,动态生成代理类(Proxy的子类),并创建代理对象;

static Object newProxyinstance

 (ClassLoader  loader,

Class<?>[ ]    interfaces,

                             InvocationHandler      h)

Proxy类的封装

采用工厂模式封装动态代理对象的创建过程:

  (1)定义一个获得动态代理对象的静态方法

  geDynamicProxy(IStringProcessing target),

  其中参数类型是业务接口

  (2)根据传递进来的目标对象,首先创建

InvocationHandler对象并设置它和目标对象

的依赖关系,然后再调用Proxy类的静态方法

newProxyInstanc(…),生成动态代理对象;

Demo:

已经实现一个接口中两个方法,现在想需要统计两个方法执行的时间。要求不能代码侵入,代理执行不能代码冗余

  1 /*
  2  * 接口
  3  */
  4 public interface IString {
  5     public void addString();//拼接字符串
  6     public void buildString();//缓存字符串
  7 }
  8 
  9 
 10 public class StringPro implements IString {
 11     private final int Amount=30000;
 12     @Override
 13     public void addString() {
 14         //核心业务代码
 15         System.out.println("adding string ...");
 16         String s="";
 17         for(int i=0;i<AMOUNT;i++){
 18             s+="A";
 19         }
 20     }
 21     
 22     @Override
 23     public void buildString() {
 24         //核心业务代码
 25         System.out.println("building string ...");
 26         stringbuilder builder=new StringBuilder();
 27         for(int i=0;i<AMOUNT;i++){
 28             builder.APPend("A");
 29         }
 30     }
 31 
 32 }
 33 
 34 
 35 import java.lang.reflect.InvocationHandler;
 36 import java.lang.reflect.Method;
 37 import java.util.Date;
 38 
 39 /*
 40  * 添加增强代码,并通过InvocationHandler减少冗余代码
 41  */
 42 public class LoginHandler implements InvocationHandler {
 43     private Object target;
 44     
 45     public Object getTraget() {
 46         return target;
 47     }
 48 
 49     public void setTraget(Object target) {
 50         this.target = target;
 51     }
 52     
 53     public LoginHandler(){}
 54     @Override
 55     public Object invoke(Object proxy, Method method, Object[] args) throws throwable {
 56         long start = system.currenttimemillis();
 57         System.out.println(new Date(start) + "开始:");
 58 
 59         // 核心业务代码
 60         
 61         /*
 62          * 重点在这里:调用关联的target对象,而不是invoke方法传入的proxy对象,
 63          * 通过这种替换可以实现调用对目标代码的增强,而不是代理对象。
 64          */
 65         Object result = method.invoke(target, args);
 66         // 增强代码
 67         long end = System.currentTimeMillis();
 68         System.out.println(new Date(end) + "结束,耗时:" + (end - start));
 69         return result;
 70     }
 71 
 72 }
 73 
 74 
 75 
 76 import java.lang.reflect.Proxy;
 77 
 78 public class ProxyFactory {
 79     public static Object getDynamicProxy(IString target){
 80         LoginHandler l = new LoginHandler();
 81         l.setTraget(target);
 82         //通过Proxy对象的静态方法创建代理对象
 83         Object proxyObject = Proxy.newProxyInstance(
 84                 target.getClass().getClassLoader(),
 85                 target.getClass().getInterfaces(), l);
 86         return proxyObject;
 87     }
 88 }
 89 
 90 
 91 
 92 
 93 import proxy.IString;
 94 import proxy.ProxyFactory;
 95 import proxy.StringPro;
 96 
 97 
 98 public class TestIoc {
 99     private static final String LOCATION = "applicationcontext.xml";
100     public static void main(String[] args) {
101         IString is = new StringPro();
102         IString dproxy =  (IString) ProxyFactory.getDynamicProxy(is);
103         System.out.println(dproxy.getClass().getName());
104         dproxy.addString();
105         System.out.println();
106         dproxy.buildString();
107     }
108 }

转载于:https://www.cnblogs.com/cxy2016/p/8506161.html

文章最后发布于: 2018-03-04 21:10:00

相关阅读

如何找到Spring的applicationContext.xml配置文件

目录 一、文章前言 二、applicationContext.xml查找 一、文章前言 Spring需要加载配置文件applicationContext.xml,那么自带的jar

【SpringMVC】关于classpath和contextConfigLocation

众所周知,基本上javaee的配置文件都放在WEB-INF之下,javaee网页工程默认读取配置文件也只会在这个目录下面读,但经常看到一些javaee

Spring MVC体系结构(一)

前言 此文章可以带领初学者们搭建Spring MVC项目,文中对MVC模式、Spring MVC的诞生背景、原理、体系结构等做了讲解,并以一个例子

Spring通过SchedulerFactoryBean实现调度任务的配置

真是越来越懒了,半年前配置过这个东西现在又忘了。找了原来的代码看了下,现在有必要将这个东西记录下来。直接上配置:<?xml version=

spring Oracle11g 的 dialect 方言选择

1、使用ojdbc-6.jar 的jar包 2、<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> 这样子就可以了

分享到:

栏目导航

推荐阅读

热门阅读