day3 反射与动态代理
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.itcast_04_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();//获取空参的构造函数
Method toStringMethod = personClass.getMethod("toString");
Object object = toStringMethod.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"));
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.itcast_04_reflect.City").isEnum()); //判断当前的Class对象表示是否是接口
System.out.println(personClass.isInterface());
System.out.println(Class.forName("cn.itcast_04_reflect.TestInterface").isInterface()); } }
.1.1. 动态代理
在之前的代码调用阶段,我们用action调用service的方法实现业务即可。
由于之前在service中实现的业务可能不能够满足当先客户的要求,需要我们重新修改service中的方法,但是service的方法不只在我们这个模块使用,在其他模块也在调用,其他模块调用的时候,现有的service方法已经能够满足业务需求,所以我们不能只为了我们的业务而修改service,导致其他模块授影响。
那怎么办呢?
可以通过动态代理的方式,扩展我们的service中的方法实现,使得在原油的方法中增加更多的业务,而不是实际修改service中的方法,这种实现技术就叫做动态代理。
动态代理:在不修改原业务的基础上,基于原业务方法,进行重新的扩展,实现新的业务。
例如下面的例子:
1、 旧业务
买家调用action,购买衣服,衣服在数据库的标价为50元,购买流程就是简单的调用。
2、 新业务
在原先的价格上可以使用优惠券,但是这个功能在以前没有实现过,我们通过代理类,代理了原先的接口方法,在这个方法的基础上,修改了返回值。
PS:我的印象里动态代理必须实现接口
传统的方法
package cn.itcast_05_proxy.service;
/**
* 这是一个业务的接口,这个接口中的业务就是返回衣服的价格
* @author wilson
*
*/
public interface IBoss {//接口
int yifu(String size);
}
package cn.itcast_05_proxy.service.impl; import cn.itcast_05_proxy.service.IBoss; /**
* 实现了卖衣服的接口
* 自定义了自己的业务,卖裤子
* @author wilson
*
*/
public class Boss implements IBoss{
public int yifu(String size){
System.err.println("天猫小强旗舰店,老板给客户发快递----衣服型号:"+size);
//这件衣服的价钱,从数据库读取
return 50;
}
public void kuzi(){
System.err.println("天猫小强旗舰店,老板给客户发快递----裤子");
}
}
package cn.itcast_05_proxy.action; import org.junit.Test; import cn.itcast_05_proxy.service.IBoss;
import cn.itcast_05_proxy.service.impl.Boss; 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);
}
}
老板自营!
天猫小强旗舰店,老板给客户发快递----衣服型号:xxl
衣服成交价:50
动态代理基础上修改
package cn.itcast_05_proxy.action; import org.junit.Test; import cn.itcast_05_proxy.proxyclass.ProxyBoss;
import cn.itcast_05_proxy.service.IBoss;
import cn.itcast_05_proxy.service.impl.Boss; /**
* 什么是动态代理? 简单的写一个模板接口,剩下的个性化工作,好给动态代理来完成!
*/
public class ProxySaleAction { /**
*使用代理,在这个代理中,只代理了Boss的yifu方法
*定制化业务,可以改变原接口的参数、返回值等
*/
@Test
public void saleByProxy() throws Exception {
IBoss boss = ProxyBoss.getProxy(10,IBoss.class,Boss.class);// 将代理的方法实例化成接口
//IBoss boss = new Boss();// 将代理的方法实例化成接口
System.out.println("代理经营!");
int money = boss.yifu("xxl");// 调用接口的方法,实际上调用方式没有变
System.out.println("衣服成交价:" + money);
}
}
package cn.itcast_05_proxy.proxyclass; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class ProxyBoss {
/**
* 对接口方法进行代理
*/
@SuppressWarnings("unchecked")
public static <T> T getProxy(final int discountCoupon,
final Class<?> interfaceClass, final Class<?> implementsClass)
throws Exception {
return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
new Class[] { interfaceClass }, new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
Integer returnValue = (Integer) method.invoke(
implementsClass.newInstance(), args);// 调用原始对象以后返回的值
return returnValue - discountCoupon;
}
});
}
}
代理经营!
天猫小强旗舰店,老板给客户发快递----衣服型号:xxl
衣服成交价:40
day3 反射与动态代理的更多相关文章
- 【Java EE 学习 24 下】【注解在数据库开发中的使用】【反射+注解+动态代理在事务中的应用service层】
一.使用注解可以解决JavaBean和数据库中表名不一致.字段名不一致.字段数量不一致的问题. 1.Sun公司给jdbc提供的注解 @Table.@Column.@Id.@OneToMany.@One ...
- Java反射和动态代理
Java反射 反射机制 RTTI 编译器在编译时打开和检查*.class文件 反射机制 运行时打开和检查*.class文件 Java反射常见的方法 java反射的应用 setAccessible(bo ...
- Java 反射 设计模式 动态代理机制详解 [ 转载 ]
Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...
- MyBatis源码解析【4】反射和动态代理
通过之前的介绍,我们了解了几个组件的生命周期. 它也是我们重要装备之一. 今天我们需要搞一件更加强的装备,叫做反射和动态代理. 如果没有这件装备的话,显然后面的源码boss是打不动的. 顺便说一下,下 ...
- Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多.要怎么理解以上这句话,请看下文. 一.反射 反射机制是 Ja ...
- Java反射机制动态代理
1.什么事反射机制动态代理 在一段代码的前后动态执行其他操作,比如有一个方法是往数据库添加一个记录,我们可以通过动态代理,在操作数据库方法的前和后添加代码执行打开数据库连接和关闭数据库连接. 2.演示 ...
- Java基础之反射和动态代理
1,反射是依赖于Class对象,然后根据Class对象,去操作该类的资源的.Class对象是发射的基石! 问题1:人这类事物用什么表示?汽车这类事物用什么表示>计算机文件用什么表示?有如此多的事 ...
- java反射实现动态代理
参考:http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html http://my.oschina.net/lyp3314/b ...
- java 27 - 9 反射之 动态代理的概述和实现
代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象. 举例:春季回家买票让人代买 动态代理: 在程序运行过程中产生的这个对象 而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以 ...
随机推荐
- day24-python操作数据库四
#!/usr/bin/env python # -*- coding:utf-8 -*- # @time: 2017/11/23 23:10 # Author: caicai # @File: dem ...
- caffe模型参数解释
作者:wjmishuai 出处: http://blog.csdn.net/wjmishuai/article/details/50890214 原始数据是28*28 1:数据层: layer { n ...
- sqlserver指定排序字段
在sqlserver中可以指定排序的字段,需要将哪个字段值排在最前面或最后面,都是可以的.见如下代码: SELECT * FROM public_comment order by case [User ...
- TCP拥塞控制和流量控制
TCP 的流量控制与拥塞控制可以说是一体的.流量控制是通过滑动窗口实现的,拥塞避免主要包含以下2个内容: (1)慢开始,拥塞避免 (2)快重传,快恢复 1.流量控制——滑动窗口 TCP采用大小可变 ...
- Myeclipse代码格式化
Shift+Ctrl+F 别和搜狗输入法冲突,把搜狗输入法的设置取消掉. 当然,还可以设置,自动格式化: 步骤:
- windows剪贴板
0x01 Windows剪贴板 Windows剪贴板是一种比较简单同时也是开销比较小的IPC(InterProcess Communication,进程间通讯)机制.Windows系统支持剪贴板IP ...
- 2.Python爬虫入门二之爬虫基础了解
1.什么是爬虫 爬虫,即网络爬虫,大家可以理解为在网络上爬行的一直蜘蛛,互联网就比作一张大网,而爬虫便是在这张网上爬来爬去的蜘蛛咯,如果它遇到资源,那么它就会抓取下来.想抓取什么?这个由你来控制它咯. ...
- 文件操作---with语句
with语句 为了避免打开文件后忘记关闭,可以通过管理上下文,即: with open('file','r','encoding='uth-8'') as f: #f为文件句柄 for line in ...
- 设置网页icon标志
下载一个你喜欢的icon,文件格式为ico,然后将这个文件重命名为favicon.ico,并把文件放在网站的根目录下. 一般在ie8版本以上都支持icon图标.但是在此版本一下,我们需要添加一段代码. ...
- <Hadoop重装><centos><NameNode失效>
Overview 记一次真真切切的NameNode单点故障. 学校机房着火之后,刀片机上的四台服务器,唯独就NameNode彻底宕掉了,去机房看了下硬盘都坏了.. 所以只能换一个master咯.基本上 ...