1.动态代理的作用
动态代理最主要的用途就是在各种框架中,很方便的在运行期间生成代理类,通过代理类就可以完成AOP、过滤器、拦截器等操作
(注:代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能(方法)进行代理的。比如UserService类有1000个业务方法,每个业务方法都都需要记录执行时间,那么不可能写1000次相同代码吧,因此可以让代理对象帮忙完成时间记录)
首先使用动态代理必须基于接口,动态代理的静态创建方法:
public static Object newProxyInstance(
ClassLoader loader,/*对象.getClass().getClassLoader() ,目标对象通过getClass方法获取类的所有信息后,调用getClassLoader()方法来获取类加载器
获取类加载器后,可以通过这个类型的加载器,在程序运行时,将生成的代理类加载到JVM即Java虚拟机中,以便运行时需要*/
Class<?>[] interfaces,/*对象.getClass().getInterfaces()
获取被代理类的所有接口信息,以便于生成的代理类可以具有代理类接口中的所有方法*/
InvocationHandler handle /*用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类方法的处理以及访问*/
)
java.lang.reflect.InvocationHandler
是代理对象的实际处理代理逻辑的接口,具体代理逻辑在其 invoke 方法中实现
public Object invoke(Object proxy, Method method, Object[] args)
**解释说明:
- 返回值:方法被代理后执行的结果
- 参数列表说明:
Object proxy : 就是代理对象(通常不使用)
Method method : 代理对象调用的方法
Object[] args : 被代理方法中的参数 (因为参数个数不定,所以用一个对象数组来表示)
如果方法不使用参数,则为 null
//所有代理对象调用的方法,执行是都会经过invoke
//因此如果要对某个方法进行代理增强,就可以在这个invoke方法中进行定义
例子:
/*其中Star是代理类接口,具有Song和Dance方法;*/
public class ProxyUtil {
public static Star createProxy(BigStar bigStar){
Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
new Class[]{Star.class}, new InvocationHandler() {
@Override // 回调方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 代理对象要做的事情,会在这里写代码
if(method.getName().equals("sing")){
System.out.println("准备话筒,收钱20万");
}else if(method.getName().equals("dance")){
System.out.println("准备场地,收钱1000万");
}
return method.invoke(bigStar, args);
}
});
return starProxy;
}
}
2.线程池的几种状态
- RUNNING : 表示正常运行,既可以接受新任务,也会正常处理阻塞队列的任务
- SHUTDOWN : 当线程池调用shutdown()方法时,进入该状态,表示线程池处于关闭状态,不会接受新任务但是会处理队列中的任务
- STOP : 调用线程池的shutdownnow()方法时,进入该状态,表示线程池处于停止状态,既不接受新任务也不处理队列任务,正常运行的线程也会被中断
- TIDYING : 线程池没有线程运行时,状态自动变为TIDYING,并且调用terminated(),该方法是空方法,留给程序与扩展
- TERMINATED : terminated()方法执行完成后,线程池就变成该状态
3.反射技术的作用,需要什么
- 反射需要Class对象
- 作用
- 不使用new关键字去创建对象
- 不使用“对象名.方法”的形式就可以调用方法
- 不使用“对象名.属性”的形式就可以给属性赋值取值
- 可以对私有成员变量进行操作
4.获取Class对象的方法
- 类型名.Class
- 对象名.getcClass
- Class.forName(String className) //className是全路径类名 = 包名+类型名
5.反射创建对象的方法
-
根据Class对象创建
Class stuClass = Class.forName("com.cls.demo2.Student"); Student stu = (Student) stuClass.newInstance(); stu.study();
-
获取构造器进行创建
//获取Class对象(Student.class) Class stuClass = Student.class; //public Student(String name, int age, String gender) //获取带有参数的构造器对象 //参数:是用来设置构造方法中参数的类型是什么 Constructor con = stuClass.getConstructor(String.class, int.class, String.class); //实例化有参构造方法 //参数:要传递给Student(String name, int age, String gender)的数据 Student stu = (Student) con.newInstance("熊大", 22, "男"); //调用对象中的方法 stu.study();
6.获取成员方法 方法调用
-
获取成员方法
每一个成员方法都是一个Method类的对象,我们可以通过Method对象来调用成员方法
Class类中的Method相关方法:
Method[] getMethods(); //获得当前类和其父类中的所有public成员方法对象,返回数组 Method[] getDeclaredMethods(); //获得当前类中的所有成员方法对象,返回数组 //只获得本类的,包括public、protected、默认、private的 Method getMethod(String name,Class...args); //根据方法名和参数类型获得对应的成员方法对象,只能获得public的 //参数说明: name : 类中方法的名字 args : 方法中参数类型的Class 例:int.class Method getDeclaredMethod(String name,Class...args); //根据方法名和参数类型获得对应的成员方法对象,包括public、protected、(默认)、private的
Method常用方法:
//使用方法对象,调用对象中的方法执行(入栈执行) Object invoke(Object obj, Object... args) // 设置"暴力访问" ——是否取消权限检查,true取消权限检查,false表示不取消 void setAccessible(true)
例子:
@Test public void testMethod2() throws ClassNotFoundException { //获取Class对象 Class stuClass = Class.forName("com.itheima.method.demo1.Student"); //使用Class对象,获取Method对象 Method[] methods = stuClass.getDeclaredMethods();//获取本类中所有方法(包含私有) for (Method m : methods){ System.out.println(m); } }
-
方法调用
反射调用对象的私有方法需要去除JVM权限检查
7.注解
-
自定义注解
public @interface 注解名{ //内容熟悉: 数据类型 属性名(); 数据类型 属性名() dalfult 默认值; }
-
元注解
定义在自定义注解上,@Target指定自定义注解修饰什么地方,@Retention指定自定义注解生命周期(有效范围)
例子
@Target({ElementType.METHOD,ElementType.TYPE}) //修饰类/接口 以及 方法 public @inference stu{ String name(); }
-
注解解析
使用反射技术完成注解数据的解析
步骤:
- 利用反射获取相关对象:类,构造器,方法,属性
- 利用方法getAnnotation,获取自定义注解的对象
- 通过注解的对象分别获取注解属性值