反射的重点掌握:
- 正向创建对象
- 反向创建对象
- Class对象的获取
- Class对象的方法:包、类、方法、属性、注解、构造方法、 父类、接口
- Class类中实例化对象的方法(默认无参构造方法)
- Constructor实例化对象(指定参数)
- 类加载器,双亲委派模型
Bootstrap ->Ext ->App ->Customer Defined - 代理:静态代理 动态代理 (JDK内置、第三方提供CGLB)、
- 注解基本使用,自定义
- 反射应用:扩展性 复用性 框架中使用(无反射不框架)
一、ClassLoader类加载器
1.ClassLoader
2.双亲委派模型(重点)
一个类文件在ClassLoder里面只会加载一次。
3.自定义类加载器
package com.wschase.reflect2;
import java.io.*;
/**自定义一个类加载器
* Author:WSChase
* Created:2019/1/20
*/
public class MyClassLoader extends ClassLoader{
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
byte[] classData=loaderClassByte(name);
if(classData==null){
throw new RuntimeException("Not found"+name);
}
return super.defineClass(name,classData,0,classData.length);
}
//name 类 ->.class
//.class文件通过文件读取的方式变成byte[]
private byte[] loaderClassByte(String name) {
File file=new File(name);
try(FileInputStream inputStream=new FileInputStream(file);
ByteArrayOutputStream outputStream=new ByteArrayOutputStream()
){
byte[] buff=new byte[1024];
int len=-1;
while ((len=inputStream.read(buff))!=-1){
outputStream.write(buff,0,len);
}
return outputStream.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
对于两个类的比较:
必须是由同一个类加载器加载的前提下才可以进行比较,不然是没有意义的。
二、反射与代理设计模式
我们先来看看我们之前的基础代理模式:
package com.wschase.reflectanddaili;
/**
* Author:WSChase
* Created:2019/1/20
*/
public class TestISubject {
public static void main(String[] args) {
ISubject realSubject=new RealSubject();
ISubject proxSubject=new ProxSubject(realSubject);
proxSubject.eate();
}
}
package com.wschase.reflectanddaili;
/**
* Author:WSChase
* Created:2019/1/20
*/
public class RealSubject implements ISubject {
@Override
public void eate() {
System.out.println("吃饭");
}
}
package com.wschase.reflectanddaili;
/**
* Author:WSChase
* Created:2019/1/20
*/
public class ProxSubject implements ISubject{
public ProxSubject(ISubject target) {
this.target = target;
}
private ISubject target;
private void prepare(){
System.out.println("准备吃饭");
}
@Override
public void eate() {
this.prepare();
this.target.eate();
this.clean();
}
private void clean(){
System.out.println("清理");
}
}
package com.wschase.reflectanddaili;
/**
* Author:WSChase
* Created:2019/1/20
*/
public class TestISubject {
public static void main(String[] args) {
ISubject realSubject=new RealSubject();
ISubject proxSubject=new ProxSubject(realSubject);
proxSubject.eate();
}
}
对于传统的代理模式我们可以看到,这样是很有弊端的,我们每次进行真正业务的时候都需要我们创建另外一个类,这样才可以实现真正的业务。
下面我们来改进代理模式,通过反射来实现代理模式:
(1)这个是传统的代理模式
/**
* Author:WSChase
* Created:2019/1/20
*/
public class TestISubject {
public static void main(String[] args) {
ISubject realSubject=new RealSubject();
ISubject proxSubject=new ProxSubject(realSubject);
proxSubject.eate();
}
}
(2)这个是工厂模式,将普通的代理模式转换为工厂模式就是将测试的那三行代码转换为如下的工厂类,这样变通更大。
package com.wschase.reflectanddaili;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* Author:WSChase
* Created:2019/1/20
*/
public class ProxFactory {
public static Object getInstance(Class realObjectClass,Class proxyObjectClass) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//实际的对象
Object realObject=realObjectClass.newInstance();
//ProxySubject(ISubject target)
//代理类的构造方法
Constructor constructor= proxyObjectClass.getConstructor(
proxyObjectClass.getInterfaces()[0]);
//代理类的构造方法获取代理对象
Object proxyObject=constructor.newInstance(realObject);
return proxyObject;
}
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
ISubject subject=(ISubject) ProxFactory.getInstance(RealSubject.class,ProxSubject.class);
subject.eate();
}
}
(3)将代理模式再次改进为:动态代理
package com.wschase.reflectanddaili;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**动态代理
* Author:WSChase
* Created:2019/1/20
*/
public class DynicProxy {
public static void main(String[] args) {
//1.被代理对象
ISubject realObject=new RealSubject();
//2.代理对象的扩展
ProxyHander hander=new ProxyHander(realObject);
//3.代理对象
ISubject ProxyObject= (ISubject) Proxy.newProxyInstance(realObject.getClass().getClassLoader(),
realObject.getClass().getInterfaces(),//这里和获得了所有的接口,同时我们可以指定具体是哪个接口->new Class[]{ISubject.class}
hander);
ProxyObject.eate();
}
}
/**
* ProxyHander:对真实类的功能进行扩展
*/
class ProxyHander implements InvocationHandler{
private Object target;
public ProxyHander(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object retVal;
System.out.println("真实对象方法执行之前增强");
retVal=method.invoke(this.target,args);
System.out.println("真实对象方法执行之后增强");
return retVal;
}
}
在java中动态代理是不需要创建对象的。但是我们还是得指定接口,如果我们下那个要将连个毫无关系的类通过代理来实现,还是由一定难度的,它是通过CGLIB来实现动态代理,我们了解一下就可以了。
三、反射与Annotation
Annotation是一个特别重要的开发技术,它的设计有一个条件:需要有代码容器擦可以实现自定义的Annotation。
1.反射取得Annotation信息
Annotation注解可以定义在类或者方法上,当我们学习完反射后就可以通过反射来取得所定义的Annotation信息。
(1)取得全部Annotation:public Annotation[] getAnnotations()
(2)取得指定的Annotation:public T getAnnotation(Class annotationClass)
(1)取得自定义在类上的Annotation
package com.wschase.annotation;
import java.io.Serializable;
import java.lang.annotation.Annotation;
/**取得定义在类上的Annotation
* Author:WSChase
* Created:2019/1/20
*/
@SuppressWarnings("serial")
@Deprecated
class Member1 implements Serializable{}
public class TestAnnotation1 {
public static void main(String[] args) {
Annotation[] ant=Member1.class.getAnnotations();
for(Annotation a:ant){
System.out.println(a);
}
}
}
(2)在方法上使用Annotation
package com.wschase.annotation;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**在方法上使用Annotation
* Author:WSChase
* Created:2019/1/20
*/
@SuppressWarnings("serial")
@Deprecated
class Member implements Serializable{
@Deprecated
@Override
public String toString(){
return super.toString();
}
}
public class TestAnnotation2 {
public static void main(String[] args) {
Annotation[] ant=new Annotation[0];
try{
ant=Member.class.getMethod("toString").getAnnotations();
}catch (NoSuchMethodException e){
e.printStackTrace();
}
for(Annotation a:ant){
System.out.println(a);
}
}
}
(3)取得某个具体的Annotation
package com.wschase.annotation;
/**取得某个具体的Annotation
* Author:WSChase
* Created:2019/1/20
*/
import java.io.Serializable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* 取得某个指定的Annotation
*/
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
public String name() default "张三";
public int age() default 20;
}
@Deprecated
@MyAnnotation2
//这个就是自定义的Annotation的注解
class Member4 implements Serializable{}
public class TestAnnotation4 {
public static void main(String[] args) {
MyAnnotation1 ma= Member4.class.getAnnotation(MyAnnotation1.class);
System.out.println("姓名:"+ma.name());
System.out.println("年龄:"+ma.age());
}
}