反射的简介
-
通过实例化对象找到所属的类别;
- “正” 通过程序所在导入包,在实例化对象,在通过对象找到类中的方法
- “反”根据实例化对象反推出所属类型。
-
获取Class对象信息:public final Class<?> getClass()
Date data = new Date();
System.out.println(data.getClass());
Class类对象的三种实例化模式
java.lang.Class类:public final class Class<T> extends Object implements Serializable, GenericDeclaration, Type, AnnotatedElement
1、【Object类支持】Object类可以根据实例化对象获取Class对象: public final Class<?> getClass()
- 这种方式有一个不是缺点的缺点:如果现在只是想获得Class类对象,则必须产生指定类对象后才可以获得;
package cn.itcast.demo.reflect;
class Person{}
public class JavaDemo {
public static void main(String[] args) {
Person per =new Person();
Class<? extends Person> cls = per.getClass();
System.out.println(cls);
System.out.println(cls.getName());//获取类的完整名称
}
}
2、【JVM直接支持】采用“类.class”的形式实例化
- 特点:如果要采用此种模式,则必须导入程序对应的开发包;
package cn.itcast.demo.reflect;
class Person{}
public class JavaDemo {
public static void main(String[] args) {
Class<? extends Person> cls = Person.class;
System.out.println(cls.getName());//获取类的完整名称
}
}
3、【Class类支持】在Class类里面提供一个static方法:
- 加载类:public static Class<?> forName(
String className
)throws ClassNotFoundException;
package cn.itcast.demo.reflect;
class Person{}
public class JavaDemo {
public static void main(String[] args) throws Exception{
Class<?> cls = Class.forName("cn.itcast.vo.Person");
System.out.println(cls.getName());//获取类的完整名称
}
}
如果此时要使用的程序类不存在则会抛出:“java.lang.ClassNotFoundException”异常。
反射实例化对象
Class提供的反射实例化对象的方法(代替了关键字new):
- 在JDK1.9以前的实例化:@Deprecated(since=“9”) public T newInstance()throws InstantiationException,IllegalAccessException
- JDK1.9以后:clazz.getDeclaredConstructor().newInstance()
package cn.itcast.demo.reflect;
class Person{}
public class JavaDemo {
public static void main(String[] args) throws Exception{
Class<?> cls = Class.forName("cn.itcast.vo.Person");
//Object obj = cls.newInstance();//JDK1.9后不在使用
Object obj = cls.getDeclaredConstructor().newInstance();//
System.out.println(obj);
}
}
反射与工厂设计模式
- 将静态的的工厂设计模式转为动态工厂模式 :
主要利用反射与泛型
package cn.itcast.demo.reflect;
import java.lang.reflect.InvocationTargetException;
public class JavaDemo {
public static void main(String[] args) throws Exception{
IMessage msg = Factory.getInstance("cn.itcast.demo.reflect.NetMessageImpl",IMessage.class);
msg.send();
IService service = Factory.getInstance("cn.itcast.demo.reflect.HouseServiceImpl", IService.class);
service.service();
}
}
/**
* 获取接口实例化对象
* @param className 接口子类
* @param clazz 描述一个接口的类型
* @author Canoe
* @return 如果之类存在则返回指定接口实例化对象
*
*/
class Factory{
private Factory() {}//没有产生实例化对象的意义,所以构造方法私有化
@SuppressWarnings("unchecked")
public static <T> T getInstance(String className , Class<T> clazz) {
T instance = null;
try {
instance = (T) Class.forName(className).getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
}
interface IService{
public void service();
}
class HouseServiceImpl implements IService{
@Override
public void service() {
System.out.println("【服务】为您提供住房服务。");
}
}
interface IMessage {
public void send();
}
class NetMessageImpl implements IMessage{
@Override
public void send() {
System.out.println("【网络消息发送】www.mldn.cn");
}
}
class CloudMessageImpl implements IMessage{
@Override
public void send() {
System.out.println("【Cloud消息发送】www.mldnjava.cn");
}
}
反射获取类结构的信息
若需要通过当前类获取父类、父接口的一些基础信息可以通过Class类中的这些方法:
- 获取包名称:public Package getPackage();
- 获取继承父类:public Class<? super T> getSuperclass();
- 获取实现父接口:public Class<?>[] getInterfaces();
反射与调用构造方法
-
实例化方法的替代: clazz.getDeclaredConstructor().newInstance()
-
获取所有的构造方法:public Constructor<?>[] getDeclaredConstructors() throws SecurityException
-
获取指定的构造方法:public Constructor getDeclaredConstructor(Class<?>… parameterTypes)throws NoSuchMethodException,
SecurityException -
获取所有构造方法:public Constructor<?>[] getConstructors()throws SecurityException
-
获取指定的构造方法:public Constructor getConstructor(Class<?>… parameterTypes)throws NoSuchMethodException,
SecurityException
反射调用普通方法:
Class类提供的获取方法对象操作:
-
获取全部方法:public Method[] getMethods()throws SecurityException
-
获取指定方法:public Method getMethod(String name,Class<?>… parameterTypes)throws NoSuchMethodException,
SecurityException -
获取本类全部方法:public Method[] getDeclaredMethods()throws SecurityException
-
获取本类指定方法:public Method getDeclaredMethod(String name,Class<?>… parameterTypes)throws NoSuchMethodException,
SecurityException -
Method类 :
反射调用类中的方法:public Object invoke(Object obj,Object... args)throws IllegalAccessException,IllegalArgumentException,
InvocationTargetException;
package cn.itcast.demo.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import cn.itcast.vo.Person1;
public class JavaDemo1 {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("cn.itcast.vo.Person1");//获取指定类的Class对象
String attribute = "name";// 要操作的类属性
String value = "小强子"; // 要设置属性的类容
//1、任何情况下如果想要保存类中的属性或者调用类中的方法都必须保证有实例化对象,既然不允许导入包,那么就反射实例化
Object obj = cls.getDeclaredConstructor().newInstance();//调用无参构造实例化
//2、如果想要进行方法调用,那么一定要获取方法的名称
String setMethodName = "setName" ;
Method setMethod = cls.getDeclaredMethod(setMethodName, String.class);//获取指定的方法
setMethod.invoke(obj, value);// 等价于: Person1对象.setName(value);
String getMethodName = "getName";
Method getMethod = cls.getDeclaredMethod(getMethodName);// getter没有参数
System.out.println(getMethod.invoke(obj));// 等价于:Person1对象.getName();
}
}
反射调用成员(Field)(成员属性)
Class类完成:
- 获取本类全部成员:public Field[] getDeclaredFields()throws SecurityException
- 获取本类指定成员:public Field getDeclaredField(String name)throws NoSuchFieldException,SecurityException
- 获取父类全部成员:public Field[] getFields()throws SecurityException
- 获取父类指定成员:public Field getField(String name)throws NoSuchFieldException,SecurityException
Class<?> cls = Class.forName("cn.itcast.vo.Person1");//获取指定类的Class对象
{
Field fields[] = cls.getFields();
for(Field fie : fields) {
System.out.println(fie);
}
}
System.out.println("-------------------");
{
Field fields[] = cls.getDeclaredFields() ;
for(Field fie : fields) {
System.out.println(fie);
}
}
Field类提供的如下的几个重要的方法:
- 设置属性内容:public void set(Object obj,Object value)throws IllegalArgumentException,IllegalAccessException
- 获取属性内容:public Object get(Object obj)throws IllegalArgumentException,IllegalAccessException
- 解出封装:public void setAccessible(boolean flag)
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("cn.itcast.vo.Person1");//获取指定类的Class对象
Object obj = cls.getDeclaredConstructor().newInstance();// 实例化对象(分配成员空间)
String setName = "name";
Field nameField = cls.getDeclaredField(setName);//获取成员对象
nameField.setAccessible(true);//没有封装了
nameField.set(obj, "番茄强");//等价于:Person1对象.name = "番茄强"
System.out.println(nameField.get(obj));//等价于:Person1对象.name
}
获取成员类型:public Class<?> getType()
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("cn.itcast.vo.Person1");//获取指定类的Class对象
Object obj = cls.getDeclaredConstructor().newInstance();// 实例化对象(分配成员空间)
String setName = "name";
Field nameField = cls.getDeclaredField(setName);//获取成员对象
System.out.println(nameField.getType().getName());//获取完整类名称“包.类”
System.out.println(nameField.getType().getSimpleName());//获取类名称
}
传统属性赋值的弊端
当类属性、类的数量大的时候,会造成大量的代码的重复,解决方案:利用反射机制,反射的最大特征可以根据其自身的特点(Object类直接操作属性或方法)实现相同功能类 的重复操作的抽象处理。
属性自动赋值实现思路
class ClassInstanceFactory{
private ClassInstanceFactory() {}
/**
* 实例化对象的创建方法,该对象可以根据传入的字符串结构“属性:内容|属性:内容”
* @param <T>
* @param clazz 进行反射实例化Class类对象,有Class就可以反射实例化对象
* @param value 要设置对象的属性内容
* @return 一个已配置好属性内容的Java类对象
*/
public static <T> T create (Class<?> clazz , String value) {
return null;
}
}
单级属性赋值
无引用关联
1、定义StringUtils实现首字母大写功能
class StringUtils {
public static String initcap(String str) {
if(str == null || "".equals(str)) {
return str;
}
if(str.length() == 1) {
return str.toUpperCase();
}else {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
}
2、定义BeanUtils工具类,该工具类主要实现属性的设置。
class BeanUtils{// 实现属性的设置
public BeanUtils() {}
/**
* 实现指定对象的属性设置
* @param obj 进行要反射操作的实例化对象
* @param value 包含指定内容的字符串,格式“属性:内容|属性:内容”
*/
public static void setValue(Object obj , String value) {
String results [] = value.split("\\|");// 按照“|”进行每一组属性的拆分
for(int x = 0 ; x <results.length ; x++) {
// attval[0]保存的是属性名称、attval[1]保存的是属性内容
String attval [] = results[x].split(":"); // 获取属性名称与内容
try {
Field field = obj.getClass().getDeclaredField(attval[0]); // 获取成员
Method setMethod = obj.getClass().getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
setMethod.invoke(obj, attval[1]); // 调用setter方法设置内容
}catch(Exception e) {}
}
}
}
3、ClassInstanceFactory负责实例化对象并且调用BeanUtils类实现属性类容的设置
class ClassInstanceFactory{
private ClassInstanceFactory() {}
/**
* 实例化对象的创建方法,该对象可以根据传入的字符串结构“属性:内容|属性:内容”
* @param <T>
* @param clazz 进行反射实例化Class类对象,有Class就可以反射实例化对象
* @param value 要设置对象的属性内容
* @return 一个已配置好属性内容的Java类对象
*/
public static <T> T create (Class<?> clazz , String value) {
try { // 如果想用采用反射进行简单java类的对象设置的时候,类必须要有无参构造
Object obj = clazz.getDeclaredConstructor().newInstance();
BeanUtils.setValue(obj, value); // 通过反射设置属性
return (T)obj; //返回对象
}catch(Exception e){
e.printStackTrace();// 如果此时真的出现了错误,本质上抛出异常也没用
return null;
}
}
}
设置多种数据类型
class BeanUtils{// 实现属性的设置
public BeanUtils() {}
/**
* 实现指定对象的属性设置
* @param obj 进行要反射操作的实例化对象
* @param value 包含指定内容的字符串,格式“属性:内容|属性:内容”
*/
public static void setValue(Object obj , String value) {
String results [] = value.split("\\|");// 按照“|”进行每一组属性的拆分
for(int x = 0 ; x <results.length ; x++) {
// attval[0]保存的是属性名称、attval[1]保存的是属性内容
String attval [] = results[x].split(":"); // 获取属性名称与内
try {
Field field = obj.getClass().getDeclaredField(attval[0]); // 获取成员
Method setMethod = obj.getClass().getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
Object convertVal = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(obj, convertVal); // 调用setter方法设置内容
}catch(Exception e) {}
}
}
/**
* 实现属性类型的转换处理
* @param type 属性类型,通过Field获取
* @param value 属性的内容 传入的都是字符串,需要将其变为指定的类型
* @return 转换后的数据
*/
private static Object convertAttributeValue(String type , String value) {
if("long".equals(type) || "java.lang.Long".equals(type)) { //长整型
return Long.parseLong(value);
}else if("int".equals(type) || "java.lang.int".equals(type)) {
return Integer.parseInt(value);
}else if("double".equals(type) || "java.lang.double".equals(type)) {
return Double.parseDouble(value);
}else if("float".equals(type) || "java.lang.float".equals(type)) {
return Float.parseFloat(value);
}else if("java.util.Date".equals(type)) {
SimpleDateFormat sdf = null;
if(value.matches("\\d{4}-\\d{2}-\\d{2}")) { // 日期类型
sdf = new SimpleDateFormat("yyyy-MM-dd");
}else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}else {
return new Date(); // 当前日期
}
try {
return sdf.parse(value);
} catch (ParseException e) {
return new Date(); // 当前日期
}
}else {
return value;
}
}
}
级联对象实例化
Company.java: | Dept.java: | Emp.java: |
---|---|---|
class Company{ private String name; private Date createdate ;} | class Dept{ private String dname; private String loc ; private Company company ;} | class Emp{ private long empno; private String ename; private String job; private double salary; private Date hiredate; private Dept dept ;} |
如果要通过Emp进行操作,则应该使用“.”作为级联关系的处理:
dept.dname:财务部 | Emp类实例化对象.getDept().setDname(“财务部”) |
---|---|
dept.company.name:MLDN | Emp类实例化对象.getDept().getCompany().setName(“MLDN”) |
使用级联关系实现对象的实例化:
String value = "empno:7278|ename:Smith|job:Clerk|salary:750.00|hiredate:1989-10-10|" +
"dept.dname:财务部|dept.company.name:MLDN";
class BeanUtils{// 实现属性的设置
public BeanUtils() {}
/**
* 实现指定对象的属性设置
* @param obj 进行要反射操作的实例化对象
* @param value 包含指定内容的字符串,格式“属性:内容|属性:内容”
*/
public static void setValue(Object obj , String value) {
String results [] = value.split("\\|");// 按照“|”进行每一组属性的拆分
for(int x = 0 ; x <results.length ; x++) {
// attval[0]保存的是属性名称、attval[1]保存的是属性内容
String attval [] = results[x].split(":"); // 获取属性名称与内
try {
if(attval[0].contains(".")) { // 多级配置
String temp[] = attval[0].split("\\.");
Object currentObject = obj ;
//System.out.println(Arrays.toString(temp));
// 最后一位肯定是指定类中属性名称,所以不再本次实例化处理范畴之内
for(int y = 0 ; y < temp.length - 1 ; y ++ ) {
// 调用相应的getter方法,如果getter返回为null表示对象未实例化
Method getMethod = currentObject.getClass().getDeclaredMethod("get" + StringUtils.initcap(temp[y]));
Object tempObject = getMethod.invoke(currentObject);
if(tempObject == null) { // 对象并没有实例化
Field field = currentObject.getClass().getDeclaredField(temp[y]);//获取属性
Method method = currentObject.getClass().getMethod("set" + StringUtils.initcap(temp[y]), field.getType());
Object newObject = field.getType().getDeclaredConstructor().newInstance();
method.invoke(currentObject, newObject);
currentObject = newObject;
}else {
currentObject = tempObject;
}
}
}else {
Field field = obj.getClass().getDeclaredField(attval[0]); // 获取成员
Method setMethod = obj.getClass().getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
Object convertVal = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(obj, convertVal); // 调用setter方法设置内容
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
/**
* 实现属性类型的转换处理
* @param type 属性类型,通过Field获取
* @param value 属性的内容 传入的都是字符串,需要将其变为指定的类型
* @return 转换后的数据
*/
private static Object convertAttributeValue(String type , String value) {
if("long".equals(type) || "java.lang.Long".equals(type)) { //长整型
return Long.parseLong(value);
}else if("int".equals(type) || "java.lang.int".equals(type)) {
return Integer.parseInt(value);
}else if("double".equals(type) || "java.lang.double".equals(type)) {
return Double.parseDouble(value);
}else if("float".equals(type) || "java.lang.float".equals(type)) {
return Float.parseFloat(value);
}else if("java.util.Date".equals(type)) {
SimpleDateFormat sdf = null;
if(value.matches("\\d{4}-\\d{2}-\\d{2}")) { // 日期类型
sdf = new SimpleDateFormat("yyyy-MM-dd");
}else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}else {
return new Date(); // 当前日期
}
try {
return sdf.parse(value);
} catch (ParseException e) {
return new Date(); // 当前日期
}
}else {
return value;
}
}
}
级联属性赋值
//进行属性内容的设置
Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]); // 获取成员
Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[temp.length - 1]), field.getType());
Object convertVal = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(currentObject, convertVal); // 调用setter方法设置内容
反射与简单java类的完整代码
package cn.itcast.demo.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import cn.itcast.vo.Person1;
public class JavaDemo1 {
public static void main(String[] args) throws Exception {
String value = "empno:7278|ename:Smith|job:Clerk|salary:750.00|hiredate:1989-10-10|" +
"dept.dname:财务部|dept.company.name:MLDN";
Emp emp = ClassInstanceFactory.create(Emp.class, value);
System.out.println("雇员编号:" + emp.getEmpno() +"、姓名:" + emp.getEname() + "、职位:" + emp.getJob() +
"、基本工资:" +emp.getSalary() + "、雇佣日期:" + emp.getHiredate());
System.out.println(emp.getDept().getDname());
System.out.println(emp.getDept().getCompany().getName());
}
}
class ClassInstanceFactory{
private ClassInstanceFactory() {}
/**
* 实例化对象的创建方法,该对象可以根据传入的字符串结构“属性:内容|属性:内容”
* @param <T>
* @param clazz 进行反射实例化Class类对象,有Class就可以反射实例化对象
* @param value 要设置对象的属性内容
* @return 一个已配置好属性内容的Java类对象
*/
public static <T> T create (Class<?> clazz , String value) {
try { // 如果想用采用反射进行简单java类的对象设置的时候,类必须要有无参构造
Object obj = clazz.getDeclaredConstructor().newInstance();
BeanUtils.setValue(obj, value); // 通过反射设置属性
return (T)obj; //返回对象
}catch(Exception e){
e.printStackTrace();// 如果此时真的出现了错误,本质上抛出异常也没用
return null;
}
}
}
class StringUtils {
public static String initcap(String str) {
if(str == null || "".equals(str)) {
return str;
}
if(str.length() == 1) {
return str.toUpperCase();
}else {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
}
class BeanUtils{// 实现属性的设置
public BeanUtils() {}
/**
* 实现指定对象的属性设置
* @param obj 进行要反射操作的实例化对象
* @param value 包含指定内容的字符串,格式“属性:内容|属性:内容”
*/
public static void setValue(Object obj , String value) {
String results [] = value.split("\\|");// 按照“|”进行每一组属性的拆分
for(int x = 0 ; x <results.length ; x++) {
// attval[0]保存的是属性名称、attval[1]保存的是属性内容
String attval [] = results[x].split(":"); // 获取属性名称与内
try {
if(attval[0].contains(".")) { // 多级配置
String temp[] = attval[0].split("\\.");
Object currentObject = obj ;
//System.out.println(Arrays.toString(temp));
// 最后一位肯定是指定类中属性名称,所以不再本次实例化处理范畴之内
for(int y = 0 ; y < temp.length - 1 ; y ++ ) {
// 调用相应的getter方法,如果getter返回为null表示对象未实例化
Method getMethod = currentObject.getClass().getDeclaredMethod("get" + StringUtils.initcap(temp[y]));
Object tempObject = getMethod.invoke(currentObject);
if(tempObject == null) { // 对象并没有实例化
Field field = currentObject.getClass().getDeclaredField(temp[y]);//获取属性
Method method = currentObject.getClass().getMethod("set" + StringUtils.initcap(temp[y]), field.getType());
//System.out.println(method);
Object newObject = field.getType().getDeclaredConstructor().newInstance();
method.invoke(currentObject, newObject);
currentObject = newObject;
}else {
currentObject = tempObject;
}
}
//进行属性内容的设置
Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]); // 获取成员
Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[temp.length - 1]), field.getType());
Object convertVal = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(currentObject, convertVal); // 调用setter方法设置内容
}else {
Field field = obj.getClass().getDeclaredField(attval[0]); // 获取成员
Method setMethod = obj.getClass().getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
Object convertVal = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(obj, convertVal); // 调用setter方法设置内容
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
/**
* 实现属性类型的转换处理
* @param type 属性类型,通过Field获取
* @param value 属性的内容 传入的都是字符串,需要将其变为指定的类型
* @return 转换后的数据
*/
private static Object convertAttributeValue(String type , String value) {
if("long".equals(type) || "java.lang.Long".equals(type)) { //长整型
return Long.parseLong(value);
}else if("int".equals(type) || "java.lang.int".equals(type)) {
return Integer.parseInt(value);
}else if("double".equals(type) || "java.lang.double".equals(type)) {
return Double.parseDouble(value);
}else if("float".equals(type) || "java.lang.float".equals(type)) {
return Float.parseFloat(value);
}else if("java.util.Date".equals(type)) {
SimpleDateFormat sdf = null;
if(value.matches("\\d{4}-\\d{2}-\\d{2}")) { // 日期类型
sdf = new SimpleDateFormat("yyyy-MM-dd");
}else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}else {
return new Date(); // 当前日期
}
try {
return sdf.parse(value);
} catch (ParseException e) {
return new Date(); // 当前日期
}
}else {
return value;
}
}
}
class Company{
private String name;
private Date createdate;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreatedate() {
return createdate;
}
public void setCreatedate(Date createdate) {
this.createdate = createdate;
}
}
class Dept{
private String dname;
private String loc ;
private Company company;
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
class Emp{
private long empno;
private String ename;
private String job;
private double salary;
private Date hiredate;
private Dept dept;
public Emp() {}
public Emp(String ename) {
this.ename = ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setJob (String job) {
this.job = job;
}
public String getEname() {
return this.ename;
}
public String getJob() {
return this.job;
}
public long getEmpno() {
return empno;
}
public void setEmpno(long empno) {
this.empno = empno;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
运行结果
雇员编号:7278、姓名:Smith、职位:Clerk、基本工资:750.0、雇佣日期:Tue Oct 10 00:00:00 CST 1989
财务部
MLDN
ClassLoader类加载器
系统类加载器:
获取ClassLoader类的对象,必须使用Class类(反射的根源)实现,方法:public ClassLoader getClassLoader(),当获取了ClassLoader之后还可以继续获取其父类的的ClassLoader类对象,方法:public final ClassLoader getParent()
自定义ClassLoader处理类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F5KgbUD8-1615020257289)(C:\Users\Canoe\AppData\Roaming\Typora\typora-user-images\image-20200504122052115.png)]
静态代理设计模式
package cn.itcast.demo.reflect;
public class JavaDemo3 {
public static void main(String[] args) {
IMessage1 msg = new MessageProxy(new MessageReal());
msg.send();
}
}
interface IMessage1{ //传统代理设计必须有接口
public void send(); //业务方法
}
class MessageReal implements IMessage1{
@Override
public void send() {
System.out.println("【发送消息】www.mlnd.cn");
}
}
class MessageProxy implements IMessage1{
private IMessage1 message; // 代理对象,一定是业务接口实例
public MessageProxy(IMessage1 message) {
this.message = message;
}
@Override
public void send() {
if(this.connect()) {
this.message.send();
this.close();
}
}
public boolean connect() {
System.out.println("【消息代理】进行消息发送通过连接");
return true;
}
public void close() {
System.out.println("【消息代理】关闭消息通道");
}
}
动态代理设计模式
- 不管是动态代理类还是静态代理类都一定要接收真实业务实现子类的对象;
- 由于动态代理类不在与某一个具体的接口进行捆绑,所以可以动态的获取类的接口信息;
InvocationHandler接口
public interface InvocationHandler{
/**
* 代理方法的调用,代理主题类里面执行的方法最终都是此方法
* @param proxy 要代理的对象
* @param method 要执行的接口方法名称
* @param args 传递的参数
* @return 某一个方法的返回值
* @throws Throwable 方法调用是出现错误继续向上抛出
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable ;
}
Proxy程序类:
-
代理对象:public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h);
- ClassLoader loader:获取当前真实主体类的ClassLoader;
- Class<?>[] interfaces:代理是围绕接口进行的,所以一定要获取真实主体类的接口信息;
- InvocationHandler h:代理处理的方法;
package cn.itcast.demo.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JavaDemo3 {
public static void main(String[] args) {
IMessage1 msg = (IMessage1) new MessageProxy().bind(new MessageReal());
msg.send();
}
}
class MessageProxy implements InvocationHandler{
private Object target; // 保存真实的业务对象
/**
* 进行真实业务对象与代理对象之间的绑定处理
* @param target 真实业务对象
* @return Proxy生成的代理对象
*/
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("【消息代理】关闭消息通道");
}
@Override
public Object invoke(Object pro, Method method, Object[] args) throws Throwable {
System.out.println("**************【执行方法】" + method);
Object returnDate = null;
if(this.connect()) {
returnDate = method.invoke(this.target, args);
}
return returnDate;
}
}
interface IMessage1{
public void send();
}
class MessageReal implements IMessage1{
@Override
public void send() {
System.out.println("【发送消息】www.mlnd.cn");
}
}
CGLIB实现基于类的代理模式
反射获取Annotation信息
AccessibleObject类:
- 获取全部Annotation:public Annotation[] getAnnotations();
- 获取指定Annotation:public T getAnnotation(Class annotationClass);
package cn.itcast.demo.reflect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class JavaDemoAnnotation {
public static void main(String[] args) throws Exception{
{ // 获取接口上的Annotation信息
Annotation annotations[] = IMessageA.class.getAnnotations();// 获取接口上的全部接口信息
for(Annotation temp : annotations) {
System.out.println(temp);
}
}
System.out.println("--------------------");
{ // 获取MessageImpl上的Annotation信息
Annotation annotations[] = MessageImpl.class.getAnnotations();// 获取接口上的全部接口信息
for(Annotation temp : annotations) {
System.out.println(temp);
}
}
System.out.println("--------------------");
{ // 获取MessageImpl上的send()方法的Annotation信息
Method method = MessageImpl.class.getDeclaredMethod("send", String.class);
Annotation annotations[] = MessageImpl.class.getAnnotations();// 获取接口上的全部接口信息
for(Annotation temp : annotations) {
System.out.println(temp);
}
}
}
}
@FunctionalInterface
@Deprecated(since="1.0")
interface IMessageA{
public void send(String str);
}
interface Serializable{}
@SuppressWarnings("serial")
class MessageImpl implements IMessageA , Serializable {
@Override
public void send(String str) {
// TODO Auto-generated method stub
}
}
自定义Annotation
语法:“@interface”
package cn.itcast.demo.reflect;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
public class JavaDemoAnnotation {
public static void main(String[] args) throws Exception{
Method method = Message.class.getMethod("send", String.class);//获取指定方法
DefautAnnotation anno = method.getAnnotation(DefautAnnotation.class);// 获取指定的Annotation
System.out.println(anno.title());//直接调用Annotation里面的方法
System.out.println(anno.url());//直接调用Annotation里面的方法
String msg = anno.title() + "(" + anno.url() + ")";
method.invoke(Message.class.getDeclaredConstructor().newInstance(), msg);
}
}
@Retention(RetentionPolicy.RUNTIME) // 定义Annotation的运行策略
@interface DefautAnnotation{ // 自定义Annotation
public String title();// 获取数据
public String url() default "www.mldn.cn";// 获取数据,默认值
}
class Message {
@DefautAnnotation(title="MLDN")
public void send(String msg ) {
System.out.println("【消息发送】" + msg);
}
}
工厂设计与代理设计与Annotation
package cn.itcast.demo.reflect;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JavaDemoFactoryProxy {
public static void main(String[] args) throws Exception{
MessageService messageService = new MessageService();
messageService.send("www.mldn.cn");
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface UseMessage{
public Class<?> clazz();
}
@UseMessage(clazz = NetMessageImplAA.class) // 利用Annotation实现了类的使用
class MessageService{
private IMessageFP message;
public MessageService() {
UseMessage use = MessageService.class.getAnnotation(UseMessage.class);
this.message =(IMessageFP) FactoryAnno.getInstance(use.clazz()); // 直接通过Annotation获取
}
public void send(String msg) {
this.message.send(msg);
}
}
@SuppressWarnings("unchecked")
class FactoryAnno{
private FactoryAnno(){}
public static <T> T getInstance(Class<T> clazz) {
try {
return (T)new MessageProxyAnno().bind(clazz.getDeclaredConstructor().newInstance());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
interface IMessageFP{
public void send(String msg) ;
}
class MessageProxyAnno 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("【代理操作】关闭消息通道");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if(this.connect()) {
return method.invoke(this.target, args);
}else {
throw new Exception("【ERROR】消息无法进行发送!");
}
}finally{
this.close();
}
}
}
class MessageImpl implements IMessageFP{
@Override
public void send(String msg) {
System.out.println("【消息发送】" + msg);
}
}
class NetMessageImplAA implements IMessageFP{
@Override
public void send(String msg) {
System.out.println("【网络消息发送】" + msg);
}
}
return (T)new MessageProxyAnno().bind(clazz.getDeclaredConstructor().newInstance());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
interface IMessageFP{
public void send(String msg) ;
}
class MessageProxyAnno 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("【代理操作】关闭消息通道");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if(this.connect()) {
return method.invoke(this.target, args);
}else {
throw new Exception("【ERROR】消息无法进行发送!");
}
}finally{
this.close();
}
}
}
class MessageImpl implements IMessageFP{
@Override
public void send(String msg) {
System.out.println("【消息发送】" + msg);
}
}
class NetMessageImplAA implements IMessageFP{
@Override
public void send(String msg) {
System.out.println("【网络消息发送】" + msg);
}
}