反射:
1.反射就是被视为动态的语言的关键,反射通过某些API来进行获取任何类中的内部信息
,并还可以进行操作任何对象内部的属性与方法
功能:
获取任意对象的属性和方法,并且还可以进行修改对应的值,
成员变量,进行构建任意一个类的对象,进行判断任意一个对象所属的类
API
java.lang.reflect 类 Method 代表类的方法
java.lang.reflect 类 Field 成员变量
java.lang.reflect 类 Constructor<t> 构造方法
3种方式
@Test
public void getVoid() throws ClassNotFoundException {
//获取Class String的实例对象
//方式一
Class cl= String.class;
//方式二
String string = new String();
Class c2= string.getClass();
//方式三
Class c3= Class.forName("java.lang.String");
System.out.println(cl == c2); //true
System.out.println(cl == c3); //true
System.out.println(c3 == c2); //true
}
Class类中常用的方法
static Class forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象 T newInstance() 创建此 Class 对象所表示的类的一个新实例。 Class getSuperclass() 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。 Class[] getInterfaces()
确定此对象所表示的类或接口实现的接口。
ClassLoader getClassLoader()
返回该类的类加载器。
Constructor<t> getConstructor(Class... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 Constructor[] getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
Field getField(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
Field[] getFields()
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
Method getMethod(String name, Class<?>... parameterTypes)
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
Method[] getMethods()
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
使用这些方法
获取构造函数
//Class的对象
Class c1= Users.class;
/*
Users users = new Users();
Class c2= users.getClass();</t></t>
Class c3= Class.forName("com.java.bo.Users");*/ // Constructor<Users>[] con= c1.getConstructors(); Constructor con01= c1.getConstructor(String.class); //System.out.println(con01); //执行多个参数的 Constructor con02= c1.getConstructor(String.class,Integer.class); // System.out.println(new Users(""));
执行并传入参数
@Test
public void getVoid01() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//Class的对象
Class c1= Users.class;
Constructor con01= c1.getConstructor(String.class);
Constructor con02= c1.getConstructor(String.class,Integer.class);
Users object= (Users) con01.newInstance("小王"); System.out.println(object); Users obj= (Users) con02.newInstance("小王",123); System.out.println(obj); }
获取构造函数的参数列表 - 得到的是参数列表的类型
@Test
public void getVoid03() throws NoSuchMethodException {
Class c1= Users.class;
// Constructor con= c1.getConstructor();
//获取构造函数 - 的所有公共构造方法
Constructor[] cons= c1.getConstructors();
//getDeclaredConstructor
// 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
//getDeclaredConstructors()
//返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
Constructor[] conss= c1.getDeclaredConstructors();
for (Constructor constructor : conss) {
//获取名称
System.out.print(constructor.getName() + "(");
//获取构造函数的参数列表- 类型
//getParameterTypes()
//按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。
Class[] typ= constructor.getParameterTypes();
for (Class aClass : typ) { System.out.print(aClass.getName()); System.out.print(" "); } System.out.print(")"); System.out.println(); } }
获取方法 Method
获取方法的名称和参数的类型
@Test
public void getVoid06(){
Class cl= Users.class;
cl.getMethods();//获取公共的
//获取所有的
Method[] met= cl.getDeclaredMethods();
for (Method method : met) {
//获取方法的返回值类型
Class clType= method.getReturnType();
System.out.print(clType.getName()+" ");
//获取方法的名称
System.out.print(method.getName() + "(");
//获取方法的参数类型
Class[] cParameter= method.getParameterTypes();
for (Class aClass : cParameter) {
//获取参数的类型
System.out.print(aClass.getName() + " ");
}
System.out.print(" )"); System.out.println(""); } }
//获取方法执行
@Test
public void getVoid04() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Users users = new Users();
Class ck= users.getClass();
//获取方法名称和类型
System.out.println("-----------方式一----------------");
//ck.getDeclaredMethods();//所有的方法
//ck.getMethods();//返回公共的
Method me=ck.getMethod("start",String.class,String.class);
Object invoke = me.invoke(users, "小女生", "老宅男");
System.out.println(invoke);
System.out.println("-----------方式二----------------");
Method me1=ck.getMethod("start",new Class[]{String.class,String.class}); Object invoke1 = me1.invoke(users, new Object[]{"隔壁老陈", "隔壁小姐姐"}); System.out.println(invoke1); } -----获取没参数的 @Test public void getVoid07() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { Users users = new Users(); Class ck= users.getClass(); //获取方法名称和类型 System.out.println("-----------方式一----------------"); //ck.getDeclaredMethods();//所有的方法 //ck.getMethods();//返回公共的 Method me=ck.getMethod("getLastAge"); Object invoke = me.invoke(users); System.out.println(invoke); System.out.println("-----------方式二----------------"); Method me1=ck.getMethod("getLastAge",new Class[]{}); Object invoke1 = me1.invoke(users,new Object[]{}); System.out.println(invoke1); }
获取对应的属性
@Test
public void getVoid01() throws ClassNotFoundException {
Class aClass = Class.forName("com.java.bo.Users");
System.out.println("获取公共属性;;;;;");
Field[] field= aClass.getFields();
for (Field field1 : field) {
System.out.println(field1.getName());
}
System.out.println("获取所有的属性---------");
Field[] fields= aClass.getDeclaredFields();
for (Field field1 : fields) {
System.out.println(field1.getName());
}
}
来进行指定设置属性的值
public void getVoid02() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
System.out.println("设置公共属性的值");
Users users =
new Users("小王",23,"小张",322);
Class aClass = Class.forName("com.java.bo.Users");
//获取到公共的属性
Field field= aClass.getField("lastName");
//之前的属性的值
String str= (String) field.get(users);
System.out.println(str);
System.out.println("------------");
//进行设置属性的值
field.set(users,"隔壁老陈");
String sr= (String) field.get(users);
System.out.println(sr);
@Test public void getVoid03() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { System.out.println("设置公共属性的值"); Users users = new Users("小王",23,"小张",322); Class aClass = Class.forName("com.java.bo.Users"); //获取到公共的属性 // Field field= aClass.getField("name"); //获取私有的 Field field= aClass.getDeclaredField("name"); //由于是私有的,那么我们需要进行设置为可用 field.setAccessible(true); //获取之前的数据信息 String sr= (String) field.get(users); System.out.println(sr); System.out.println("-----------"); //设置新的数据信息 field.set(users,"隔壁老王"); String sr1= (String) field.get(users); System.out.println(sr1); System.out.println("-----------"); System.out.println(users); }
案列
@Test
public void getVoid01() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList<String> strings = new ArrayList<>(); Class ck= strings.getClass(); ArrayList stri = new ArrayList<>(); Class ck01= stri.getClass(); System.out.println(ck == ck01);//ture strings.add("小王"); Method met=ck.getMethod("add",Object.class); met.invoke(strings,123156); System.out.println(strings); }
动态代理
CGLIB后面讲解
1.动态代理,是指客户通过代理类来进行调用其他的对象方法,并且是在程序运行的时候,根据需求来进行动态的创建目标类
的代理对象
如:地主家的傻大儿子, 找个贴身丫鬟,
2.代理设计模式的原理 1.使用一个代理将对象包装起来,然后用该代理对象取代原始对象 2.任何对原始对象的调用都要通过代理对象来进行实现 3.代理对象决定是否以及何时来进行调用原始对象上的方法。
Proxy
1.使用动态代理必须要有一个接口,那么有了接口就有对应的实现类
接口
public interface IUsersDao {
public void login();
public void submit();
}
实现
public class UsersDaoImp implements IUsersDao {
@Override
public void login() {
//开启事务 。数据验证
System.out.println("-----------我进行登录了");
//关闭事务 日志的记录
}
@Override public void submit() { //开启事务 。数据验证 System.out.println("我进行提交了-----------------"); //关闭事务 日志的记录 } } 代理 public class MyUsersDaoImp implements InvocationHandler { private Object object; public MyUsersDaoImp(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("数据验证----的业务逻辑"); //进行调用原始对象的需要执行的方法 如 login 和 submit 方法 method.invoke(object,args); System.out.println("日志记录的业逻辑"); return null; } }
调用
public static void main(String[] args) { UsersDaoImp usersDaoImp = new UsersDaoImp(); /*usersDaoImp.login(); usersDaoImp.submit();*/ System.out.println("---------------"); MyUsersDaoImp myUsersDaoImp = new MyUsersDaoImp(usersDaoImp); //使用动态代理的Proxy 类进行实现代理调用的方法 //newProxyInstance 返回一个指定接口的代理类实例 /* * loader - 定义代理类的类加载器 interfaces - 代理类要实现的接口列表 h - 指派方法调用的调用处理程序 * */ IUsersDao iUsersDao = (IUsersDao) Proxy.newProxyInstance(usersDaoImp.getClass().getClassLoader(), usersDaoImp.getClass().getInterfaces(), myUsersDaoImp); iUsersDao.login(); System.out.println("-------"); iUsersDao.submit(); }