《Java编程思想》读书笔记 第十四章 02 反射
2017-07-14 本文已影响28人
goule1994
《Java编程思想》读书笔记 第十四章 02 反射
反射机制
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为反射
反射机制的功能及实现
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
- 生成动态代理
将反射机制应用于工厂模式
interface Fruit {
public abstract void eat();
}
class Apple implements Fruit {
public void eat() { System.out.println("Apple"); }
}
class Orange implements Fruit {
public void eat() { System.out.println("Orange"); }
}
class Factory {
public static <T> T getInstance(String className) {
T obj = null;
try {
obj = (T) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
}
public class TestReflect4 {
public static void main(String[] args) throws Exception {
Fruit fruit = Factory.getInstance("Apple");
if (fruit != null)
fruit.eat();
}
}
动态代理
代理是一本基本的设计模式;代理通常充当着中间人的角色
==静态代理:==
interface Interface {
void doSomething();
void somethingElse(String arg);
}
class RealObject implements Interface {
public void doSomething() {
System.out.println("doSomething");
}
public void somethingElse(String arg) {
System.out.println("somethingElse " + arg);
}
}
class SimpleProxy implements Interface {
private Interface profixed;
public SimpleProxy(Interface profixed) {
this.profixed = profixed;
}
public void doSomething() {
System.out.println("SimpleProxy doSomething");
profixed.doSomething();
}
public void somethingElse(String arg) {
System.out.println("SimpleProxy somethingElse " + arg);
profixed.somethingElse(arg);
}
}
public class SimpleProxyDemo {
public static void consumer(Interface iface) {
iface.doSomething();
iface.somethingElse("bonobo");
}
public static void main(String[] args) {
consumer(new RealObject());//直接操作RealObject对象
//通过SimpleProxy代理类对象间接操作RealObject对象
consumer(new SimpleProxy(new RealObject()));
}
}
==jdk动态代理:==
http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy: 指代我们所代理的那个真实对象
method: 指代的是我们所要调用真实对象的某个方法的Method对象
args: 指代的是调用真实对象某个方法时接受的参数
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载//TODO
interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,
如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),
这样我就能调用这组接口中的方法了
h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
举例:
//首先我们定义了一个Subject类型的接口,为其声明了两个方法:
public interface Subject
{
public void rent();
public void hello(String str);
}
//接着,定义了一个类来实现这个接口,这个类就是我们的真实对象,RealSubject类:
public class RealSubject implements Subject
{
@Override
public void rent()
{
System.out.println("本身自己的方法");
}
@Override
public void hello(String str)
{
System.out.println("hello: " + str);
}
}
//下一步,我们就要定义一个动态代理类了,前面说个,每一个动态代理类都必须要实现 InvocationHandler 这个接口,因此我们这个动态代理类也不例外:
public class DynamicProxy implements InvocationHandler
{
//这个就是我们要代理的真实对象
private Object subject;
//构造方法,给我们要代理的真实对象赋初值
public DynamicProxy(Object subject)
{
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("我来代理你,带你飞");
System.out.println("**** proxy: " + proxy.getClass().getName()
+ ", method: " + method + ", args: " + args);
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(subject, args);
//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("代理完成,安全降落");
return null;
}
/**
* <T>向下转型
* @param <T>
* @return
*/
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(
subject.getClass().getClassLoader(),
subject.getClass().getInterfaces(),
this
);
}
}
//最后,来看看我们的Client类:
public class Client
{
public static void main(String[] args)
{
// 我们要代理的真实对象
Subject realSubject = new RealSubject();
// 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
DynamicProxy handler = new DynamicProxy(realSubject);
/*
* 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
* 参数1:ClassLoader
* 参数2:该实现类的所有接口
* 参数3:动态代理对象。
*/
SubjectService subject = handler.getProxy();
subject.rent();
subject.hello("啦啦啦!!!");
}
}
==cligb动态代理:==
https://my.oschina.net/huangyong/blog/159788
public class CGLibProxy implements MethodInterceptor {
public <T> T getProxy(Class<T> cls) {
return (T) Enhancer.create(cls, this);
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("我来代理你,带你飞");
System.out.println("**** proxy: " + proxy.getClass().getName()
+ ", method: " + method + ", args: " + args);
Object result = proxy.invokeSuper(obj, args);
System.out.println("代理完成,安全降落");
return result;
}
}
单利模式:
public class CGLibProxy implements MethodInterceptor {
private static CGLibProxy instance = new CGLibProxy();
//限制外界不能再去new
private CGLibProxy() {
}
public static CGLibProxy getInstance() {
return instance;
}
public <T> T getProxy(Class<T> cls) {
return (T) Enhancer.create(cls, this);
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("我来代理你,带你飞");
System.out.println("**** proxy: " + proxy.getClass().getName()
+ ", method: " + method + ", args: " + args);
Object result = proxy.invokeSuper(obj, args);
System.out.println("代理完成,安全降落");
return result;
}
}
public class Test {
public static void main(String[] args) {
//jdk动态代理
SubjectServiceImpl subjectService = new SubjectServiceImpl();
DynamicProxy handler = new DynamicProxy(subjectService);
SubjectService subject = handler.getProxy();
subject.rent();
subject.hello("啦啦啦!!!");
//Cglib动态代理
CGLibProxy cgLibProxy = new CGLibProxy();
SubjectServiceImpl subjectProxy = cgLibProxy.getProxy(SubjectServiceImpl.class);
subjectProxy.rent();
subjectProxy.hello("啦啦啦");
//单利模式cglib动态代理
SubjectServiceImpl subjectProxy = CGLibProxy.getInstance().getProxy(SubjectServiceImpl.class);
subjectProxy.rent();
subjectProxy.hello("啦啦啦");
}
}
我一向都是以追求完美而著称,2 行代码返回代理对象,我觉得还是有些多余,我不想总是去 new 这个 CGLibProxy 对象,最好 new 一次,以后随时拿随时用。于是我想到了“单例模式”