一、注解(Annotation)
从JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是 Annotation(注解)
可以说注解就相当于一个修饰符,可以修饰包,变量,方法,类等
三个基本的Annotation:
1).@Override 这个注解很熟悉了,只能修饰方法,标上此注解就表明该方法重写了父类的方法
2).@Deprecated 用于表示某个程序元素(类, 方法等)已过时,变量或者方法标上此注解后,在调用时会出现"已过时"的标记
有些时候有些方法或者属性的确已经过时了,但其他一些方法中也的确调用过这类方法,所以这些过时方法也不能删除,
但是我们希望以后不在使用这些方法,就可以加上@Deprecated
3).@SuppressWarnings 抑制编译器警告,通常的用法为:@SuppressWarnings("unchecked"),即不检查警告
自定义一个注解
pbulic @interface Overload
{
//定义注解的一个属性
String value();
}
Annotation的属性声明方式:String name();
Annotation属性默认值声明方式:String name() default “xxx”;
特殊属性value:如果注解中有一个名称为value的属性,那么使用注解时,可以省略value=部分,例如:@MyAnnotation(“xxx")
元Annotation指修饰Annotation的Annotation,以下列举了几种:
@Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留的域,
@Rentention 包含一个 RetentionPolicy 类型的成员变量, 通过这个变量指定域。
RetentionPolicy.CLASS: 编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注释. 这是默认值
RetentionPolicy.RUNTIME:编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注释. 程序可以通过反射获取该注释
RetentionPolicy.SOURCE: 编译器直接丢弃这种策略的注释
@Target: 指定注解用于修饰类的哪个成员. @Target 包含了一个名为 value 的成员变量.
@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档.
@Inherited: 被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自动具有该注解其中比较常用的@Retention(RetentionPolicy.RUNTIME)
指定注解修饰方法还是变量 @Target(value = {ElementType.METHOD, ElementType.FIELD}),修饰类的注解不用写@Target
二、类加载器
类加载器负责将 .class 文件(可能在磁盘上, 也可能在网络上) 加载到内存中, 并为之生成对应的 java.lang.Class 对象
当 JVM 启动时,会形成由三个类加载器组成的初始类加载器层次结构:
bootstrap classloader:引导(也称为原始)类加载器,它负责加载Java的核心类。这个加载器的是非常特殊的,它实际上不是 java.lang.ClassLoader的子类,而是由JVM自身实现的,因为JVM在启动的时候就自动加载它们,所以不需要在系统属性CLASSPATH中指定这些类库
extension classloader:扩展类加载器,它负责加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或者由java.ext.dirs系统属性指定的)中的JAR包。这为引入除Java核心类以外的新功能提供了一个标准机制。因为默认的扩展目录对所有从同一个JRE中启动的JVM都是通用的,
所以放入这个目录的 JAR类包对所有的JVM和system classloader都是可见的
Appclassloader: 系统(也称为应用)类加载器,它负责在JVM被启动时,加载来自在命令java中的-classpath或者java.class.path系统属性或者 CLASSPATH操作系统属性所指定的JAR类包和类路径。
上面摘抄了一些文章,三种类加载器介绍的很详细
classloader 加载类用的是全盘负责委托机制
全盘负责:
我们写了一个类Person,由类加载器classloader来加载,假如Person类中还调用了其他类,则这些其他类被加载的类加载器
通常也是加载Person类的加载器
委托机制:
比方我们调用了一个类(不管是核心类,扩展类还是自己编写的类),加载的时候首先会去找父类的加载器,然后父类的加载器就推给爷爷加载器
一级级往上推,当super的加载器可以加载,那就加载此类,如果不行就往下推,下面的能加载就加载,不行的话在往下推,就这样直到类被加载
三、动态代理
这块只是挺抽象的,因为目前学到的知识中还没有动态代理的一些应用场景,所以总结起来就相对很无奈...
从开始学Java SE时,我们就明白了万物皆对象,在java里,每个对象都有一个类与之对应
现在要生成某一个对象的代理对象,这个代理对象也要通过一个类来生成,所以首先要编写用于生成代理对象的类,举个例子
自定义一个Person类
class Person
{
public void sing(){System.out.println("sing")}
public void dance(){System.out.println("dance")}
}
这里需要说明一点,被代理对象必须要实现某个接口,这个不暂时还不知道为什么,应该是一种机制吧
interface Pe
{
void sing();
void dance();
}
然后创建一个代理对象来包装Person类的对象
如何编写生成代理对象的类,有两个要素:
代理谁: 这个我们需要在编写代理类的时候就要指定需要被代理的对象
如何生成被代理对象: 设计一个方法生成代理对象(这个地方有歧义,我理解但写不出来,这个方法返回的代理对象可不是new一个我们编写的代理类,方法返回的对象是JavaAPI提供的一个代理类Proxy生成的对象)
咱们来编写代理类
class PersonProxy
{
private Person person;
public PersonProxy(Person person)
{
this.person = person;
}
public Object getProxyPerson()
{
}
}
getProxyPerson()返回的是一个Object类型,方法该如何写,这是个难点
咱们查询下API,参考下Proxy类,发现有一个类似newInstance的方法,有戏...
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
来好好研究下这些参数:
ClassLoader loader 表示用的哪个加载器,这个好办,咱们写的代理类用的是哪个就写哪个 即:PersonProxy.class.getClassLoaderI();
Class<?>[] interfaces 怎么为Person类创建代理对象,那么此处的接口就是被代理对象实现的接口 即:person.getClass().getInterfaces();
InvocationHandler h 这个参数的意思就是咱们产生了制定的代理对象,需要这个对象干些什么事情呢
查询API发现InvocationHandler是个接口,匿名内部类实现其方法
new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}
这些参数的意思我也不大明白,就那么用着
method参数我感觉就相当于反射类的方法时得到的一个Method对象,然后method可以调用invoke方法来 调用被反射的类中的那个方法
这个方法会返回一个Object类型的,因为我们并不知道以后要代理的对象道理是什么类型的,所以当我们使用这个生成的代理对象时,可能
需要强转成被代理的类型
main方法
public class Demo
{
public static void main(String[] args)
{
Persn per = new Person();
PersonProxy pp = new PersonProxy(per); //包装了被代理的对象
Object obj = pp.getProxyPerson(); //调用生成代理对象的方法,返回Object类型
//然后将obj强转成我们需要被代理的对象的类型
Pe pe = (Pe)obj;
}
}
看强转的那块,只能用接口类型的变量来指向这个对象,其实很好理解,通常来说咱们是要代理Person类的对象,但Person必须要实现一个接口
归根到底还是到接口那里了,开始我也很不理解,到最后想出了这个借口,勉强把自己糊弄过去了, 恩恩,很强大
总之,记住就好
三、内省
1.Introspector
Java 语言对 Bean 类属性的一种缺省处理方法
对于一个JavaBean文件,如何访问里面的属性,通常情况下我们是去反射setter和getter方法,然后method.invoke来set或者get
面对这种情况,Java提供了一套API可以专门访问Bean类的属性,其实这套API的底层也是采用了反射的技术
① 通过类 Introspector 来获取某个对象的 BeanInfo 信息
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
② 然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor)
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
这个数组中存放的都是Bean属性
③ 通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法, 然后通过反射机制来调用这些方法
这里是需要判断的,咱们可以先打印出所有属性的名字,然后想修改哪个属性在来判断,比如:
for(PropertyDescriptor descriptor : descriptors)
{
System.out.println(descriptor.getName()); //打印出所有的属性
System.out.println(descriptor.getReadMethod().getName()); //打印出所有的get方法的名字,也包括getClass()
//注意:这里貌似不能全部打印出set方法的名字,会抛NullPointException异常,Why?
if ("name".equals(descriptor.getName())) //判断属性的名字
descriptor.getWriteMethod().invoke(per, "Tom"); //设置属性的内容,参数分别为被修改的对象,和修改的内容
}
相关推荐
Java IOC(Inversion of Control,控制反转)和AOP(Aspect-Oriented ...在源码和工具方面,我们可以学习到如何利用Java的内省API进行类信息的获取,以及如何利用反射和动态代理来实现依赖注入和面向切面编程。
反射是Java提供的一种强大的动态类型机制,它允许程序在运行时检查类的信息,如类名、属性、方法等,并能够创建和操作对象。Java.lang.reflect包提供了Class、Constructor、Method和Field等类来支持反射操作。 内省...
- 动态代理类的设计通常包括代理接口、目标对象、代理对象和InvocationHandler。 ##### 7. 编写可生成代理和插入通告的通用方法 - 可以编写通用方法来自动生成代理对象,并在调用前后插入通知。 ##### 8. 实现类似...
- 动态代理提供了在运行时创建接口的代理实例的能力。 10. **类加载器**: - 类加载器是Java运行时环境的一部分,负责加载类文件到虚拟机中。 11. **XML解析技术**: - 介绍了XML解析技术的概况,包括JAXP、DOM...
3.7.1. 字符串方法的历史注解 3.8. 小结 4. 自省的威力 4.1. 概览 4.2. 使用可选参数和命名参数 4.3. 使用 type、str、dir 和其它内置函数 4.3.1. type 函数 4.3.2. str 函数 4.3.3. 内置函数 4.4. 通过 ...
- 代理:学习动态代理和静态代理,理解AOP(面向切面编程)。 - 装箱/拆箱:了解自动装箱和拆箱的机制,减少类型转换的繁琐。 - 静态引用:了解静态导入和静态方法的使用。 3. **JavaEE技术** - XML基础:理解...
- **动态代理**:讨论注解与动态代理之间的联系,以及如何利用注解实现AOP编程。 #### 类加载器机制 - **Bootstrap ClassLoader**:介绍Bootstrap ClassLoader的特点和加载路径。 - **Extension ClassLoader**:...
这种能力常用于创建代理对象、动态实现接口或增强已有类的功能。`minimalcode-reflect`可能集成了字节码生成技术,使得开发者能更灵活地创建符合需求的JavaBean实例。 4. **注解处理(Annotation Processing)**:...
- **动态代理应用**:通过示例代码展示如何实现动态代理。 ### 13. 类加载器 - **类加载过程**:介绍类是如何被加载到JVM中的。 - **类加载器种类**:解释不同的类加载器(Bootstrap ClassLoader、Extension ...
**7.20 Tip:动态代理应用** - **示例**: - 记录方法调用日志 - 进行权限验证 **7.21 类加载器** - **分类**: - Bootstrap ClassLoader - Extension ClassLoader - System ClassLoader **7.22 Bootstrap ...
内省是Java API的一部分,用于在运行时检查对象的属性和方法,主要用于实现动态代理、Bean属性操作等。 10. 代理(Proxy): Java的动态代理机制允许在运行时创建一个实现了指定接口的代理对象,代理对象可以拦截...
- **动态代理**:动态创建实现特定接口的对象,常用于AOP。 2. **Java多线程与并发**: - **线程Join、notify、notifyAll**:协调多线程间执行,避免死锁。 - **线程池**:有效管理线程资源,提高系统效率。 - ...
- **动态代理应用**:例如,可以通过动态代理为对象添加额外的行为,如日志记录、性能监控等。 #### 九、类加载器 类加载器是Java运行时环境的重要组成部分,负责加载类到JVM中。 - **类加载器**:主要有...
JDK5引入的动态代理机制,允许在运行时创建实现了特定接口的新类。这在AOP(面向切面编程)中尤为有用,可以方便地实现拦截器、日志、事务管理等功能。 十、类型推断(Type Inference) JDK5的类型推断主要体现在...
- **概念**:动态代理是在运行时创建代理对象的技术。 - **实现方式**:使用Java的Proxy类或者CGLIB库。 **7.20 Tip:动态代理应用** - **应用场景**:例如AOP(面向切面编程)中使用动态代理实现日志记录等功能。...
4. **动态代理**:Java的Proxy类和InvocationHandler接口利用反射实现动态代理,可以创建满足特定接口的代理对象。 5. **框架开发**:许多Java框架如Spring、Hibernate都大量使用反射来实现依赖注入、AOP等高级功能...
JDK5增强了Java的内省能力,允许在运行时获取类的信息,如字段、方法等,这对于反射API的使用和动态代理等高级功能至关重要。 9. **并发改进(Concurrency Enhancements)** 在JDK5中,对多线程编程进行了大量...