苏州正规网站建设概况,中华建设杂志网站,网页平面设计公司,做箱包外贸哪个网站好目录 1.反射与代理设计模式
2.反射与Annotation
3.自定义Annotation
4.Annotation整合工厂设计模式和代理设计模式 1.反射与代理设计模式
代理模式是指通过业务真实类实现业务接口#xff0c;再通过设置代理类创建业务真实类子类从而间接访问业务真实类。但是这存在一个弊…目录 1.反射与代理设计模式
2.反射与Annotation
3.自定义Annotation
4.Annotation整合工厂设计模式和代理设计模式 1.反射与代理设计模式
代理模式是指通过业务真实类实现业务接口再通过设置代理类创建业务真实类子类从而间接访问业务真实类。但是这存在一个弊端如果有1000个业务接口对应的业务就需要实例化1000个对象如下
代理设计模式
package Example1709;
//业务接口实现发送消息
interface Message{public void send();
}
//业务接口真实实现
class MessageReal implements Message{Overridepublic void send() {System.out.println(传输信息Message);}
}
//代理类
class Proxy{
// 通过实例化子类进行间接实现功能private MessageReal real new MessageReal();public void getMessage() {real.send();}
}
public class javaDemo {public static void main(String[] args) {Proxy p new Proxy();p.getMessage();}
}可以看到代理类里面创建了Message实例对象通过代理设计就可以实现客户端无需创建相应对象就能调用其中方法只需要创建代理类即可。但是如果业务非常多而我仅需要其中一个业务功能那么代理类创建的对象将浪费。所以可以通过反射实现动态代理 java中特地有InvocationHandle接口实现动态代理只需要让代理类实现该接口并且覆写其中方法invoke方法调用 就能实现动态代理 案例代码
package Example1710;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//业务接口
FunctionalInterface
interface Message{public void send();
}
interface Connect{public boolean connect();
}
interface Close{public void close();
}
//业务实现类
class MessageReal implements Message{Overridepublic void send() {System.out.println(输出信息);}
}
class ConnectReal implements Connect{Overridepublic boolean connect() {System.out.println(连接成功);return true;}
}
class closeReal implements Close{Overridepublic void close() {System.out.println(断开连接);}
}
//代理类需要实现InvocationHandle接口
class MessageProxy implements InvocationHandler {private Object object;public Object bind(Object object){this.object object;return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);}
//覆写InvocationHandle接口中的invoke方法实现方法的调用Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(当调用方法时候自动执行这个函数);Object returnData null;returnData method.invoke(this.object,args);return returnData;}
}
public class javaDemo {public static void main(String[] args) {
// 向上转型实现需要的代理类Connect con (Connect) new MessageProxy().bind(new ConnectReal());con.connect();}
}2.反射与Annotation
在java.lang.reflect中通过AccesibleObject类可以获取Annotation注解。
AccessibleObject类获取Annotation的方法
方法名返回类型描述getAnnotations()Annotation[]返回直接存在于此元素上的所有注解。getAnnotation(ClassT annotationClass)T extends Annotation T如果此元素上存在指定类型的注解则返回该注解否则返回 null。getDeclaredAnnotations()Annotation[]返回直接存在于此元素上的所有已声明注解。getDeclaredAnnotation(ClassT annotationClass)T extends Annotation T如果此元素上存在指定类型的注解则返回该注解否则返回 null。isAnnotationPresent(Class? extends Annotation annotationClass)boolean如果此元素上存在指定类型的注解则返回 true否则返回 false。
案例代码
package Example1711;import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;Deprecated
FunctionalInterface
interface Face{void face();
}SuppressWarnings(serial)
class Test implements Face, Serializable {Overridepublic void face() {System.out.println(No face);}
}public class javaDemo {public static void main(String[] args) {Annotation tation[] Face.class.getAnnotations();for (Annotation temp:tation) {System.out.println(temp);}Annotation taion2[] Test.class.getAnnotations();for (Annotation temp:taion2) {System.out.println(temp);}}
}上图中可以发现输出的只有interface接口的注解Annotation 但是类的上面的还有类内部的Override却没有输出。原因在于Annotation的定义范围有关
下面任意拆出一个注解比如FunctionInterface分析源码
Documented
Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
public interface FunctionalInterface{}
可以看到其中还定义的范围是Rentention这里是RUNTIME意思是运行 Retention注解用于指定注解的保留策略有三个可选值 RetentionPolicy.SOURCE注解只保留在源代码中编译时会被忽略。RetentionPolicy.CLASS注解保留在编译后的字节码文件中但在运行时无法获取到。RetentionPolicy.RUNTIME注解保留在编译后的字节码文件中并且可以在运行时通过反射获取到。 问1Connect con (Connect) new MessageProxy().bind(new ConnectReal());其中new MessageProxy是创建代理对象那return Proxy.newProxyInstance(object.getClass().getClassLoader()this)也是创建代理对象这不是重复了操作吗如果和new MessageProxy作用不一样的话那么newProxyInstance方法有什么作用 3.自定义Annotation
开发者可以根据自己的需要自定义Annotation其中定义Annotaion时候需要使用interface进行标记同时通过Target定义范围
Annotation操作范围:
元素类型Target 取值描述类或接口ElementType.TYPE应用于类、接口或枚举类型。字段ElementType.FIELD应用于字段成员变量。方法ElementType.METHOD应用于方法。构造方法ElementType.CONSTRUCTOR应用于构造方法。方法参数ElementType.PARAMETER应用于方法的参数。局部变量ElementType.LOCAL_VARIABLE应用于局部变量。注解ElementType.ANNOTATION_TYPE应用于注解类型。包ElementType.PACKAGE应用于包声明。泛型类型参数ElementType.TYPE_PARAMETER应用于泛型类型参数。泛型类型参数的边界ElementType.TYPE_USE应用于泛型类型参数的使用处例如类型转换、instanceof 表达式等类型导入声明Java 9ElementType.TYPE_IMPORT_DECLARATION应用于类型导入声明。模块导入声明Java 9ElementType.MODULE_IMPORT_DECLARATION应用于模块导入声明。类型使用ElementType.TYPE_USE 或 ElementType.TYPE_PARAMETER应用于类型使用或泛型类型参数。 自定义案例代码
如果DefaultInterface对象有必要的数据传入可以在interface下设置value值。 package Example1713;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;Target({ElementType.METHOD,ElementType.TYPE})
Retention(RetentionPolicy.RUNTIME)
interface useMessage{public String title();public String value();public String Default()default 默认值如果调用则返回这个默认;
}class Message {useMessage(titleAnnotation的使用标题,value value的值)public void send(String str){System.out.println(输出信息str);}
}
public class javaDemo {public static void main(String[] args) throws Exception{String str;
// 调用方法Method mehod Message.class.getMethod(send, String.class);
// 获取指定的AnnotationuseMessage msg mehod.getAnnotation(useMessage.class);str msg.Default();
// 实现方法调用mehod.invoke(Message.class.getDeclaredConstructor().newInstance(),str);str msg.title();mehod.invoke(Message.class.getDeclaredConstructor().newInstance(),str);str msg.value();mehod.invoke(Message.class.getDeclaredConstructor().newInstance(),str);}
}4.Annotation整合工厂设计模式和代理设计模式
使用Annotation进行开发时候最大的特点就是可以将相应的配置信息写入Annotation后在项目启动的时候就能够通过反射获取到相应的Annotation定义并操作
以下案例实现了通过Annotation整合工厂设计模式和代理设计模式
案例代码
package Example1714;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//业务接口
interface Message{public void send(String msg);
}
//业务实现类
class NetMessageImp implements Message{Overridepublic void send(String msg) {System.out.println(通过网络进行发送消息msg);}
}
class CloudMessageImp implements Message{Overridepublic void send(String msg) {System.out.println(通过云网络进行发送消息msg);}
}
//定义工厂类
class Factory{
// 私有化工厂类无法在外部实例化private Factory(){};
// 通过getInstance获取实例化的对象public staticT T getInstance(ClassT clazz){try {return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance());} catch (Exception e){e.printStackTrace();return null;}}
}
//设置自定义Annotation
Target({ElementType.TYPE,ElementType.METHOD})
Retention(RetentionPolicy.RUNTIME)
interface RealInstance {public Class? claszz();}RealInstance(claszz NetMessageImp.class)
class MessageService{private Message msg;public MessageService(){
// getAnnotation需要对应的classRealInstance cls MessageService.class.getAnnotation(RealInstance.class);this.msg (Message) Factory.getInstance(cls.claszz());}public void send(String msg){this.msg.send(msg);}
}
//设置代理类
class MessageProxy implements InvocationHandler{private Object target;
// 绑定并创建指定对象public Object bind(Object target){this.target target;return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);}
// 设置连接函数public boolean connect(){System.out.println(连接成功);return true;}
// 设置关闭函数public void close(){System.out.println(断开连接);}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {if (this.connect()){return method.invoke(this.target,args);}}catch (Exception e){e.printStackTrace();}finally {this.close();}return null;}
}
public class javaDemo {public static void main(String[] args) {MessageService instance new MessageService();instance.send(我去这东西是真的复杂啊需要好好仔细读完啊);}
}Message接口是一个业务接口定义了发送消息的方法。NetMessageImp和CloudMessageImp是两个实现了Message接口的具体业务类分别通过网络和云网络发送消息。Factory是一个工厂类通过使用代理模式创建并返回代理对象的实例。RealInstance是一个自定义注解用于标记需要被代理的具体业务类。MessageService是一个具有注解的类其中msg字段是通过工厂类创建的代理对象用于发送消息。MessageProxy是一个实现了InvocationHandler接口的代理类负责在发送消息前后进行额外的处理比如连接和关闭连接。在主函数中创建MessageService实例并调用send方法发送消息。 问1public staticT T getInstance(ClassT clazz)为什么要用T,作为泛型方法是如何使用的? public static T T getInstance(ClassT clazz)中的T是泛型声明它允许我们在方法中使用泛型类型。其中T是一个类型参数表示方法的返回类型和传入参数的类型。通过在方法声明中使用泛型我们可以在调用时指定具体的类型并在编译时进行类型检查。 问2在这段整合工厂设计和代理设计时候工厂类和代理类分别担任了什么样的角色他们完成了什么职责为什么要加入MessageService? 工厂类Factory的角色是创建并返回代理对象的实例。它的职责是根据传入的业务接口类型使用代理模式创建该接口的代理对象。工厂类的目的是为了提供一种通用的方式来创建代理对象。代理类MessageProxy的角色是实现了InvocationHandler接口的代理类。它的职责是在代理对象的方法调用前后进行额外的处理。在这个例子中它负责在发送消息前后进行连接和关闭连接的操作。MessageService是一个业务类其中的msg字段通过工厂类创建的代理对象用于发送消息。MessageService通过使用代理对象可以在发送消息的过程中加入额外的处理逻辑而无需直接引用具体的业务实现类。 问3Proxy.newProxyInstance()方法如何使用,该怎么传入参数 Proxy.newProxyInstance()方法用于创建代理对象。它接受三个参数 ClassLoader loader类加载器用于在运行时加载代理类。一般可以使用业务接口的类加载器。Class?[] interfaces代理类要实现的接口数组。代理对象将实现这些接口并将方法调用委托给InvocationHandler的invoke()方法。InvocationHandler h代理对象在方法调用时的处理器需要实现InvocationHandler接口 问4方法调用method.invoke()如何传入参数 问4method.invoke()方法用于调用代理对象的方法。它接受两个参数 Object obj方法所属的对象即代理对象。Object... args方法的参数数组。 问5在设计模式中工厂设计模式代理设计模式业务处理类的作用 在设计模式中工厂模式的作用是将对象的创建过程封装起来并且提供一个统一的接口来获取对象的实例。通过使用工厂类可以实现对象的创建和管理的解耦使得代码更加灵活和可维护。代理模式的作用 代理模式充当了客户端和实际业务对象之间的中介角色为客户端提供一种间接访问对象的方式。具体来说代理类封装了实际业务对象并提供了一个类似的接口使得客户端可以通过代理类来访问实际业务对象。代理类还可以在访问被代理对象之前或之后执行额外的逻辑例如验证、缓存、日志记录等。代理模式的优点是它可以在不修改客户端的情况下对实际业务对象进行控制和扩展。业务处理类的作用 业务处理类是实际执行业务逻辑的类。它是根据特定需求实现业务功能的地方。在代理模式中业务处理类是被代理的真实对象。它定义了代理类需要代理的具体业务逻辑代理类会将请求传递给业务处理类并最终由业务处理类完成实际的业务操作。