动态代理
动态代理的作用
1.为什么需要代理?
代理可以无侵入式的给对象增强其他功能
2.代理长什么样子?
代理里面就是对象要被代理的方法
3.Java通过什么来保证代理的样子?
通过接口保证,后面的对象和代理需要实现同一个接口
接口中就是被代理的对象
如何为JAVA对象创建一个代理对象?
java.lang.reflect.Proxy类:提供一个为对象产生代理对象的方法:
实例
public interface Star {
public abstract String sing(String name);
public abstract void dance();
}
public class BigStar implements Star{
private String name;
public BigStar() {
}
public BigStar(String name) {
this.name = name;
}
//唱歌
@Override
public String sing(String name){
System.out.println(this.name + "正在唱" + name);
return "谢谢";
}
//跳舞
@Override
public void dance(){
System.out.println(this.name + "正在跳舞");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class ProxyUtil {
public static Star createProxy(BigStar bigStar){
Star star = (Star) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(),//参数一:用于指定哪个类加载器,去加载生成的代理类
new Class[]{Star.class},//参数二:指定接口,这些接口用于指定生成的代理长什么,也就是说有哪些方法
new InvocationHandler() {
//参数三:用来指定生成的代理对象要干什么事
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*
参数一:代理的对象
参数二:要运行的方法 sing
参数三:调用sing方法时,传递的实参
*/
if("sing".equals(method.getName())){
System.out.println("准备话筒,收钱");
}else if("dance".equals(method.getName())){
System.out.println("准备场地,收钱");
}
//找大明星开始唱歌或跳舞
//代码的表现形式:调用大明星里面唱歌或跳舞的方法
return method.invoke(bigStar,args);
}
});
return star;
}
}
测试
public class test {
public static void main(String[] args) {
/**
* 需求:
* 外面的人想要明星唱一首歌
* 1.获取代理的对象
* 代理对象 = ProxyUtil.class
* 2.再调用代理的唱歌方法
* 代理对象,唱歌的方法("只因你太美")
*/
//1.获取代理的对象
BigStar bigStar = new BigStar("鸡哥");
Star proxy = ProxyUtil.createProxy(bigStar);
//2.调用唱歌的方法
String result = proxy.sing("只因你太美");
proxy.dance();
System.out.println(result);
}
}
反射
什么是反射?
反射允许对成员变量,成员方法和构造方法的信息进行编程访问
获取class对象的三种方式
代码实例
public class MyReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
/**
* 获取class对象的三种方式:
* 1.Class.forName(“全类名");
* 2.类名.class
* 3.对象.getClass();
*/
//1.第一种方式
//全类名:包名 + 类名
//最为常用
Class clazza1= Class.forName("com.itjuzi.Studnet");
//2.第二种方式
//一般更多的是当做参数进行传递
Class clazz2 = Studnet.class;
//3.第三种方式
//当我们已经有了这个类的对象时,才可以使用
Studnet s = new Studnet();
Class clazz3 = s.getClass();
System.out.println(clazz3 == clazza1);
}
}
利用反射获取构造方法
public class MyReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
/**
* 获取class对象的三种方式:
* 1.Class.forName(“全类名");
* 2.类名.class
* 3.对象.getClass();
*/
//1.第一种方式
//全类名:包名 + 类名
//最为常用
Class clazza1= Class.forName("com.itjuzi.Studnet");
//2.获取构造方法
// Constructor[] constructors = clazza1.getConstructors();
// for(Constructor con: constructors) {
// System.out.println(con);
// }
//3.获取所有构造方法
// Constructor[] cons2 = clazza1.getDeclaredConstructors();
// for(Constructor con: cons2) {
// System.out.println(con);
// }
//4.获取单个的构造方法
// Constructor con1 = clazza1.getDeclaredConstructor();
// System.out.println(con1);
// Constructor con1 = clazza1.getDeclaredConstructor(String.class);
// System.out.println(con1);
// Constructor con1 = clazza1.getDeclaredConstructor(int.class);
// System.out.println(con1);
Constructor con2 = clazza1.getDeclaredConstructor(String.class,int.class);
// int modifiers = con2.getModifiers();
// System.out.println(modifiers);
//
// Parameter[] parameters = con2.getParameters();
// for(Parameter parameter:parameters){
// System.out.println(parameter);
// }
//暴力反射:临时取消权限的校验
con2.setAccessible(true);
Studnet student = (Studnet) con2.newInstance("张三", 23);
System.out.println(student);//Studnet{name='张三', age=23}
}
}
利用反射获取成员变量
public class MyReflectDemo3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//1.获取class字节码文件的对象
Class clazz = Class.forName("com.itjuzi.Studnet");
//2.获取成员变量
Field[] fields = clazz.getFields();
for(Field field : fields){
System.out.println(field);
}
System.out.println("*********************");
//2.获取所有成员变量
Field[] fieldss = clazz.getDeclaredFields();
for(Field field : fieldss){
System.out.println(field);
}
System.out.println("*********************");
//2.获取单个成员变量
Field gender = clazz.getField("gender");
System.out.println(gender);
System.out.println("*********************");
Field name = clazz.getDeclaredField("name");
System.out.println(name);
System.out.println("*********************");
//获取权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
System.out.println("*********************");
//获取成员变量的名字
String n = name.getName();
System.out.println(n);
//获取成员变量的数据类型
Class<?> type = name.getType();
System.out.println(type);
//获取成员变量记录的值
Studnet studnet = new Studnet("张三四",23,"男");
name.setAccessible(true);
Object value = name.get(studnet);
System.out.println(value);
//修改里面的值
name.set(studnet,"lisi");
System.out.println(studnet);
}
}
利用反射获取成员方法
public class MyReflectDemo4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1.获取class字节码文件的对象
Class clazz = Class.forName("com.itjuzi.Studnet");
//2.获取所有的方法对象(父类中的所有的公工方法)
Method[] methods = clazz.getMethods();
for(Method method: methods){
System.out.println(method);
}
System.out.println("**************************");
//2.获取所有的方法对象(不能获取父类的,但是可以获取本类中私有的
Method[] methodss = clazz.getDeclaredMethods();
for(Method method: methodss){
System.out.println(method);
}
System.out.println("**************************");
//2.获取指定的单一方法
Method eat = clazz.getDeclaredMethod("eat", String.class);
System.out.println(eat);
//获取方法的修饰符
int modifiers = eat.getModifiers();
System.out.println(modifiers);
//获取方法的名字
String name = eat.getName();
System.out.println(name);
//获取方法的形参
Parameter[] parameters = eat.getParameters();
for(Parameter parameter : parameters){
System.out.println(parameter);
}
//获取方法的返回值
//获取方法抛出的异常
final Class<?>[] exceptionTypes = eat.getExceptionTypes();
for(Class exceptionType : exceptionTypes){
System.out.println(exceptionType);
}
//方法运行
/*
Method类用于创建对象的方法
Object invoke(Object obj, Object ...args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
参数三:调用方法的返回值(如果没有就不写)
*/
Studnet s = new Studnet();
//参数一s:表示方法的调用者
//参数二“汉堡包":表示在调用方法的时候传递的实际参数
eat.setAccessible(true);
String result = (String) eat.invoke(s, "汉堡包");
System.out.println(result);
}}
反射的作用
①获取一个类里面的所有的信息,获取到之后,再执行其他的业务逻辑
②结合配置文件,动态的创建对象并调用方法
保存信息
public class MyReflectDemo {
public static void main(String[] args) throws IllegalAccessException, IOException {
/*
对于任意一个对象,都可把所有的字段名和值保存到文件中去
*/
Student s = new Student("小a",23, '女',156.4,"睡觉");
Teacher t = new Teacher("波妞",1000);
saveObject(s);
}
//把对象里面所有的成员变量名和值都保存到本地文件中
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
//1.获取字节码文件的对象
Class claz = obj.getClass();
//创建IO流
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\a_java_workspace\\java_daili\\myreflect5\\a.txt"));
//2.获取所有的成员变量
Field[] declaredFields = claz.getDeclaredFields();
for (Field field :declaredFields){
field.setAccessible(true);
//获取成员变量的名字
String name = field.getName();
//获取成员变量的值
Object value = field.get(obj);
//写出数据
bw.write(name + "=" + value);
bw.newLine();
}
bw.close();
}
}
public class MyReflectDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
/*
反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
*/
//1.读取配置文件的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("D:\\a_java_workspace\\java_daili\\myreflect6\\src\\main\\resources\\prop.properties");
prop.load(fis);
System.out.println(prop);
//2.获取群里面和方法名
String classname = (String) prop.get("classname");
String method = (String) prop.get("method");
//3.利用反射创建对象并运行方法
Class clazz = Class.forName(classname);
//获取构造方法
Constructor construct = clazz.getDeclaredConstructor();
Object o = construct.newInstance();
System.out.println(o);
//获取成员方法并运行
Method mehtod = clazz.getDeclaredMethod(method);
mehtod.setAccessible(true);
mehtod.invoke(o);
}
}
1.反射的作业
①获取任意一个类中的所有信息
②结合配置文件动态创建对象
2.获得class字节码文件对象的三种方式
①Class.forName(“全雷名”);
②类名.class
③对象.getClass();
3.如何获取构造方法、成员方法、成员变量
get:获取 set :设置
Constructor:构造方法 Parameter:参数
Field:成员变量 Modifiers:修饰符
Method:方法 Declared:私有的