java动态代理、反射

Ø java动态代理、反射

.1.1.   反射

通过反射的方式可以获取class对象中的属性、方法、构造函数等,一下是实例:

        

package cn.java.reflect;

 

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.List;

 

import org.junit.Before;

import org.junit.Test;

 

public class MyReflect {

         public String className = null;

         @SuppressWarnings("rawtypes")

         public Class personClass = null;

         /**

          * 反射Person类

          * @throws Exception

          */

         @Before

         public void init() throws Exception {

                  className = "cn.java.reflect.Person";

                  personClass = Class.forName(className);

         }

         /**

          *获取某个class文件对象

          */

         @Test

         public void getClassName() throws Exception {

                  System.out.println(personClass);

         }

         /**

          *获取某个class文件对象的另一种方式

          */

         @Test

         public void getClassName2() throws Exception {

                  System.out.println(Person.class);

         }

         /**

          *创建一个class文件表示的真实对象,底层会调用空参数的构造方法

          */

         @Test

         public void getNewInstance() throws Exception {

                  System.out.println(personClass.newInstance());

         }

         /**

          *获取非私有的构造函数

          */

         @SuppressWarnings({ "rawtypes", "unchecked" })

         @Test

         public void getPublicConstructor() throws Exception {

                  Constructor  constructor  = personClass.getConstructor(Long.class,String.class);

                  Person person = (Person)constructor.newInstance(100L,"zhangsan");

                  System.out.println(person.getId());

                  System.out.println(person.getName());

         }

         /**

          *获得私有的构造函数

          */

         @SuppressWarnings({ "rawtypes", "unchecked" })

         @Test

         public void getPrivateConstructor() throws Exception {

                  Constructor con = personClass.getDeclaredConstructor(String.class);

                  con.setAccessible(true);//强制取消Java的权限检测

                  Person person2 = (Person)con.newInstance("zhangsan");

                  System.out.println(person2.getName());

         }

         /**

          *获取非私有的成员变量

          */

         @SuppressWarnings({ "rawtypes", "unchecked" })

         @Test

         public void getNotPrivateField() throws Exception {

                  Constructor  constructor  = personClass.getConstructor(Long.class,String.class);

                  Object obj = constructor.newInstance(100L,"zhangsan");

                 

                  Field field = personClass.getField("name");

                  field.set(obj, "lisi");

                  System.out.println(field.get(obj));

         }

         /**

          *获取私有的成员变量

          */

         @SuppressWarnings({ "rawtypes", "unchecked" })

         @Test

         public void getPrivateField() throws Exception {

                  Constructor  constructor  = personClass.getConstructor(Long.class);

                  Object obj = constructor.newInstance(100L);

                 

                  Field field2 = personClass.getDeclaredField("id");

                  field2.setAccessible(true);//强制取消Java的权限检测

                  field2.set(obj,10000L);

                  System.out.println(field2.get(obj));

         }

         /**

          *获取非私有的成员函数

          */

         @SuppressWarnings({ "unchecked" })

         @Test

         public void getNotPrivateMethod() throws Exception {

                  System.out.println(personClass.getMethod("toString"));

                 

                  Object obj = personClass.newInstance();//获取空参的构造函数

                  Object object = personClass.getMethod("toString").invoke(obj);

                  System.out.println(object);

         }

         /**

          *获取私有的成员函数

          */

         @SuppressWarnings("unchecked")

         @Test

         public void getPrivateMethod() throws Exception {

                  Object obj = personClass.newInstance();//获取空参的构造函数

                  Method method = personClass.getDeclaredMethod("getSomeThing");

                  method.setAccessible(true);

                  Object value = method.invoke(obj);

                  System.out.println(value);

 

         }

         /**

          *

          */

         @Test

         public void otherMethod() throws Exception {

                  //当前加载这个class文件的那个类加载器对象

                  System.out.println(personClass.getClassLoader());

                  //获取某个类实现的所有接口

                  Class[] interfaces = personClass.getInterfaces();

                  for (Class class1 : interfaces) {

                           System.out.println(class1);

                  }

                  //反射当前这个类的直接父类

                  System.out.println(personClass.getGenericSuperclass());

                  /**

                   * getResourceAsStream这个方法可以获取到一个输入流,这个输入流会关联到name所表示的那个文件上。

                   */

                  //path 不以’/'开头时默认是从此类所在的包下取资源,以’/'开头则是从ClassPath根下获取。其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源。

                  System.out.println(personClass.getResourceAsStream("/log4j.properties"));

                  //默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源。

                  System.out.println(personClass.getResourceAsStream("/log4j.properties"));

                 

                  //判断当前的Class对象表示是否是数组

                  System.out.println(personClass.isArray());

                  System.out.println(new String[3].getClass().isArray());

                 

                  //判断当前的Class对象表示是否是枚举类

                  System.out.println(personClass.isEnum());

                  System.out.println(Class.forName("cn.java.reflect.City").isEnum());

                 

                  //判断当前的Class对象表示是否是接口

                  System.out.println(personClass.isInterface());

                  System.out.println(Class.forName("cn.java.reflect.TestInterface").isInterface());

                 

                 

         }

}

 

 

.1.2.   动态代理

         在之前的代码调用阶段,我们用action调用service的方法实现业务即可。

         由于之前在service中实现的业务可能不能够满足当先客户的要求,需要我们重新修改service中的方法,但是service的方法不只在我们这个模块使用,在其他模块也在调用,其他模块调用的时候,现有的service方法已经能够满足业务需求,所以我们不能只为了我们的业务而修改service,导致其他模块授影响。

         那怎么办呢?

         可以通过动态代理的方式,扩展我们的service中的方法实现,使得在原油的方法中增加更多的业务,而不是实际修改service中的方法,这种实现技术就叫做动态代理。

         动态代理:在不修改原业务的基础上,基于原业务方法,进行重新的扩展,实现新的业务。

         例如下面的例子:

1、  旧业务

买家调用action,购买衣服,衣服在数据库的标价为50元,购买流程就是简单的调用。

2、  新业务

在原先的价格上可以使用优惠券,但是这个功能在以前没有实现过,我们通过代理类,代理了原先的接口方法,在这个方法的基础上,修改了返回值。

         代理实现流程:

1、  书写代理类和代理方法,在代理方法中实现代理Proxy.newProxyInstance

2、  代理中需要的参数分别为:被代理的类的类加载器soneObjectclass.getClassLoader(),被代理类的所有实现接口new Class[]{ Interface.class },句柄方法newInvocationHandler()

3、  在句柄方法中复写invoke方法,invoke方法的输入有3个参数Object proxy(代理类对象), Method method(被代理类的方法),Object[]args(被代理类方法的传入参数),在这个方法中,我们可以定制化的开发新的业务。

4、  获取代理类,强转成被代理的接口

5、  最后,我们可以像没被代理一样,调用接口的认可方法,方法被调用后,方法名和参数列表将被传入代理类的invoke方法中,进行新业务的逻辑流程。

                  原业务接口IBoss

public interface IBoss {//接口

         int yifu(String size);

}

原业务实现类

public class Boss implements IBoss{

         public int yifu(String size){

                  System.err.println("天猫小强旗舰店,老板给客户发快递----衣服型号:"+size);

                  //这件衣服的价钱,从数据库读取

                  return 50;

         }

         public void kuzi(){

                  System.err.println("天猫小强旗舰店,老板给客户发快递----裤子");

         }

}

原业务调用

public class SaleAction {

                  @Test

         public void saleByBossSelf() throws Exception {

                  IBoss boss = new Boss();

                  System.out.println("老板自营!");

                  int money = boss.yifu("xxl");

                  System.out.println("衣服成交价:" + money);

         }

}

代理类

public static IBoss getProxyBoss(final int discountCoupon) throws Exception {

         Object proxedObj = Proxy.newProxyInstance(Boss.class.getClassLoader(),

                           new Class[] { IBoss.class }, new InvocationHandler() {

                                    public Object invoke(Object proxy, Method method,

                                                      Object[] args) throws Throwable {

                                                      Integer returnValue = (Integer) method.invoke(new Boss(),

                                                                        args);// 调用原始对象以后返回的值

                                                      return returnValue - discountCoupon;

                                    }

                           });

         return (IBoss)proxedObj;

}

}

新业务调用

public class ProxySaleAction {

                  @Test

         public void saleByProxy() throws Exception {

                  IBoss boss = ProxyBoss.getProxyBoss(20);// 将代理的方法实例化成接口

                  System.out.println("代理经营!");

                  int money = boss.yifu("xxl");// 调用接口的方法,实际上调用方式没有变

                  System.out.println("衣服成交价:" + money);

         }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值