通过反射获取类的完整结构
1、获取对应的运行时类的属性(Field)
public void testField1(){
Class clazz= Person.class;
System.out.println(clazz);
Field[] fields=clazz.getDeclaredFields();
for(Field field:fields){
System.out.println(field.getName());
}
}
public void testField2(){
Class clazz= Person.class;
Field[] fields=clazz.getDeclaredFields();
for(Field field:fields){
int i=field.getModifiers();
String str=Modifier.toString(i);
System.out.print(str+" ");
Class type=field.getType();
System.out.print(type.getSimpleName()+" ");
System.out.print(field.getName());
System.out.println();
}
}
2、获取对应的运行时类的方法(Method)
public void testMethod1(){
Class clazz= Person.class;
Method[] methods=clazz.getDeclaredMethods();
for(Method method:methods){
System.out.println(method.getName());
}
}
public void testMethod2() {
Class clazz = Person.class;
Method[] methods=clazz.getDeclaredMethods();
for(Method method:methods){
Annotation[] annotations=method.getAnnotations();
for(Annotation annotation:annotations){
System.out.println(annotation);
}
int i=method.getModifiers();
String type=Modifier.toString(i);
System.out.print(type+" ");
Class cla=method.getReturnType();
System.out.print(cla.getSimpleName()+" ");
System.out.print(method.getName()+" ");
System.out.print("(");
Class[] params=method.getParameterTypes();
for(int j=0;j<params.length;j++){
if(j!=params.length-1){
System.out.print(params[j].getSimpleName()+" args-"+j+",");
}else{
System.out.print(params[j].getSimpleName()+" args-"+j);
}
}
System.out.print(")");
Class[] cl=method.getExceptionTypes();
if(cl.length>0){
System.out.print("throws ");
}
for(int k=0;k<cl.length;k++){
System.out.println(cl[k].getSimpleName());
}
System.out.println();
}
}
3、获取对应的运行时类的构造器(Constructor)
public void testConstructor(){
Class clazz=Person.class;
Constructor[] constructors=clazz.getDeclaredConstructors();
for(Constructor constructor:constructors){
int i=constructor.getModifiers();
String type=Modifier.toString(i);
System.out.print(type+" ");
System.out.print(clazz.getSimpleName());
System.out.print("(");
Class[] cls=constructor.getParameterTypes();
for(int j=0;j< cls.length;j++){
if(j!=cls.length-1){
System.out.print(cls[j].getSimpleName()+" args-"+j+",");
}else{
System.out.print(cls[j].getSimpleName()+" args-"+j);
}
}
System.out.println("){");
System.out.println("}");
}
}
4、获取运行时类的父类(Class)
public void testSuperClass(){
Class clazz=Person.class;
Class superClass=clazz.getSuperclass();
System.out.println(superClass.getSimpleName());
}
5、获取运行时类的带泛型的父类(Class)
public void testGenericSuperClass(){
Class clazz=Person.class;
Type type=clazz.getGenericSuperclass();
System.out.println(type);
}
6、获取运行时类的父类的泛型(Type)
public void testGenericSuperClassType(){
Class clazz=Person.class;
Type type=clazz.getGenericSuperclass();
if(type instanceof ParameterizedType){
ParameterizedType parameterizedType=(ParameterizedType) type;
Type[]typeArgs=parameterizedType.getActualTypeArguments();
if(typeArgs!=null && typeArgs.length>0){
for(Type args:typeArgs){
if(args instanceof Class){
Class c=(Class)args;
System.out.println(c.getSimpleName());
}
}
}
}
}
7、获取运行时类实现的接口(Interface)
public void testInterface(){
Class clazz=Person.class;
Class[] cls=clazz.getInterfaces();
for(Class c:cls){
System.out.println(c.getSimpleName());
}
}
8、获取运行时类所在的包(Package)
public void testPackage(){
Class clazz=Person.class;
Package pack=clazz.getPackage();
System.out.println(pack.getName());
}
9、获取运行时类的注释()
public void test11(){
Class clazz=Person.class;
Annotation[] annotations=clazz.getAnnotations();
for(Annotation annotation:annotations){
System.out.println(annotation);
}
}
小结
1、在实际的操作中,取得类的信息的操作代码,并不会经常开发
2、一定要熟悉java.lang.reflect包的作用,反射机制
3、如何取得属性、方法、构造器的名称,修饰符等
通过反射调用类中的指定方法、指定属性、指定构造器
1、调用运行时类中的指定属性(Field)
public void testField3()throws Exception{
Class clazz=Person.class;
Field name=clazz.getDeclaredField("name");
Person p=(Person)clazz.newInstance();
System.out.println(p);
name.setAccessible(true);
name.set(p,"Jerry");
Field age=clazz.getDeclaredField("age");
age.setAccessible(true);
age.set(p,18);
int a=(int)age.get(p);
System.out.println(p);
}
2、调用运行时类中的指定方法(Method)
public void testMethod3()throws Exception{
Class clazz=Person.class;
Method m1=clazz.getDeclaredMethod("show");
Person p=(Person) clazz.newInstance();
m1.invoke(p);
System.out.println(m1.invoke(p));
Method m2=clazz.getDeclaredMethod("toString");
m2.invoke(p);
System.out.println(m2.invoke(p));
Method m3=clazz.getMethod("info");
m3.invoke(Person.class);
Method m4=clazz.getDeclaredMethod("display",String.class,Integer.class);
m4.setAccessible(true);
m4.invoke(p,"中国",10);
System.out.println(m4.invoke(p,"中国",10));
}
3、调用指定的构造器(Constructor),创建运行时类对象
public void testConstructor2()throws Exception{
Class clazz=Person.class;
Constructor constructor=clazz.getDeclaredConstructor(String.class,int.class);
constructor.setAccessible(true);
Person p=(Person) constructor.newInstance("灵棋",16);
System.out.println(p);
}
Object invoke(Object obj, Object … args)说明
1、Object 对应原方法的返回值,若原方法无返回值,此时返回null
2、若原方法若为静态方法,此时形参Object obj可为null
3、若原方法形参列表为空,则Object[] args为null
4、若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法
java静态代理
interface ClothFactory{
void productCloth();
}
class NikeClothFactory implements ClothFactory{
@Override
public void productCloth() {
System.out.println("Nike工厂生产一批衣服");
}
}
class ProxyFactory implements ClothFactory{
private ClothFactory cf;
public ProxyFactory(ClothFactory cf){
System.out.println("代理类开始执行,收代理费$1000");
this.cf=cf;
}
@Override
public void productCloth() {
cf.productCloth();
}
}
public class TestClothProduct {
public static void main(String[] args) {
NikeClothFactory nike=new NikeClothFactory();
ProxyFactory proxy=new ProxyFactory(nike);
proxy.productCloth();
}
}
特征
1、代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展
2、每一个代理类只能为一个接口服务,程序开发中必然产生过多的代理
3、最好可以通过一个代理类完成全部的代理功能(jdk动态代理)
java动态代理
特征
1、客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
2、 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理,代理对象决定是否以及何时将方法调用转到原始对象上
3、Proxy:专门完成代理的操作类,是所有动态代理类的父类。通过此类为一个或多个接口动态地生成实现类。
interface Subject{
void action();
}
class RealSubject implements Subject{
@Override
public void action() {
System.out.println("我是被代理类,记得要执行我");
}
}
class MyInvocationHandler implements InvocationHandler{
Object obj;
public Object blind(Object obj){
this.obj=obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnVal=method.invoke(obj,args);
return returnVal;
}
}
public class TestProxy {
public static void main(String[] args) {
RealSubject real=new RealSubject();
MyInvocationHandler handler=new MyInvocationHandler();
Object obj=handler.blind(real);
Subject sub=(Subject)obj;
sub.action();
NikeClothFactory nike=new NikeClothFactory();
ClothFactory proxyCloth=(ClothFactory) handler.blind(nike);
proxyCloth.productCloth();
}
}
动态代理与AOP
1、通常都是为指定的目标对象生成动态代理
2、AOP代理里的方法可以在执行目标方法之前、之后插入一些通用处理
interface UserService{
public void login();
public Integer queryUserCount();
}
class UserServiceImpl implements UserService{
@Override
public void login() {
System.out.println("userServiceImp login");
}
@Override
public Integer queryUserCount() {
System.out.println("userServiceImp queryUserCount..");
return 0;
}
}
class ServiceUtil{
public void method1(){
System.out.println("方法一");
}
public void method2(){
System.out.println("方法二");
}
}
class JdkProxyFactory{
private Object obj;
public JdkProxyFactory(Object obj){
this.obj=obj;
}
public Object getProxyInstance(){
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),new MyFirstInvocationHandler());
}
class MyFirstInvocationHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ServiceUtil serviceUtil=new ServiceUtil();
serviceUtil.method1();
Object returnVal=method.invoke(obj,args);
serviceUtil.method2();
return returnVal;
}
}
}
public class TestAOP {
public static void main(String[] args) {
UserService service=new UserServiceImpl();
JdkProxyFactory factory=new JdkProxyFactory(service);
UserService proxyService=(UserService)factory.getProxyInstance();
proxyService.login();
System.out.println();
proxyService.queryUserCount();
}
}