1、概念:
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
2、应用:
获取类的的属性对象、构造器对象、方法对象、注解信息
3、动态获取类模板的三种方式:
//1、Class.forName(类的路径和类名,最常用)
Class<?> c = Class.forName("java.lang.String");
//2、使用对象的getClass方法(运用不广泛)
String str = "";
Class<?> cStr=str.getClass();//从对象上面获取模板
//3、使用类型的 class 属性,可以用任意一种数据类型
Class<Integer> cint=int.class;
Class<?> cString=String.class;
//注 :多个同类型的对象,获取到的信息是同一个类对象
String str1=new String("123");
String str2=new String("456");
System.out.println(str1.getClass()==str2.getClass());
//结果是:true
4、通过读取properties配置文件实例化对象:
配置文件:object.properties
className=com.gxa.pojo.Car
field.logo=BMW
field.price=3
Demo:
//1、读取配置文件
Properties properties = new Properties();
InputStream inputStream = AppTest.class.getClassLoader().getResourceAsStream("object.properties");
properties.load(inputStream);
//2、获取类模板
Class<?> className = Class.forName(properties.getProperty("className"));
//3、获取属性值
String logo = (String) properties.getProperty("field.logo");
Integer price = Integer.valueOf(properties.getProperty("field.price")) ;
//4、通过构造函数创建对象并赋值
Object o = className.getConstructor(String.class,Integer.class).newInstance(logo,price);
System.out.println(o);
//结果: Car{logo='BMW', price=3, user=null}
5、通过Dom4j读取xml配置文件实例化对象:
解决思路:
1、以面向对象的思想将xml文件内标签实例化对象:分别是bean和property对象,标签内的属性就是对象的属性。
2、先创建对象,将对象放入容器,再给对象注入属性,如果有ref标签属性,在容器寻找对应的对象并注入进去。
Dom4j依赖:
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
xml配置文件:spring.xml
<beans >
<bean name="user" class="com.gxa.pojo.User">
<property name="userName" value="tom" />
<property name="userAge" value="20" />
<property name="car" ref="car"></property>
</bean>
<bean name="car" class="com.gxa.pojo.Car">
<property name="logo" value="BMW" />
<property name="price" value="50" />
</bean>
</beans>
pojo类:
//对应<bean>标签
public class Bean {
private String name;//name属性
private String className;//class属性
private List<Property> list=new ArrayList<>();//property 类
}
//对应<property >标签
public class Property {
private String name;//name属性
private String value;//value属性
private String ref;//ref属性
}
工具类–解析xml:
/**
* 解析xml,并且封装结果集
*/
public class ParseXmlUtil {
//输入流
private static InputStream inputStream;
//bean对象容器
private static List<Bean> beanList=new ArrayList<>();
//实例对象容器
private static Map<String,Object> map=new HashMap<>();
static {
/**
* 类加载器获取流,是在java根目录下寻找资源
*/
inputStream = ParseXmlUtil.class.getClassLoader().getResourceAsStream("spring.xml");
//解析xml文件
parse();
//实例化bean
initBean();
//实例化Property
initProperty();
}
/**
* 解析xml
*/
private static void parse() {
SAXReader reader = new SAXReader();
try {
Document document = reader.read(inputStream);
Element root = document.getRootElement();
List<Element> beans = root.elements("bean");
for (Element element : beans) {
String name = element.attributeValue("name");
String aClassName = element.attributeValue("class");
Bean beanObj = new Bean(name, aClassName);
beanList.add(beanObj);
List<Element> property = element.elements("property");
for (Element element1 : property) {
String name1 = element1.attributeValue("name");
String value = element1.attributeValue("value");
String ref = element1.attributeValue("ref");
Property property1 = new Property(name1, value, ref);
beanObj.getList().add(property1);
}
}
// System.out.println(beanList);
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 初始化bean
*/
private static void initBean(){
/**
* 1、判断beanList是否为空
* 2、实例化对象
* 3、将对象方式mapr容器
*/
if (beanList.size()>0) {
for (Bean bean : beanList) {
String name = bean.getName();
String className = bean.getClassName();
// System.out.println(name);
// System.out.println(className);
try {
Class<?> aClass = Class.forName(className);
Object object = aClass.getConstructor().newInstance();
map.put(name,object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
// System.out.println(map);
}
}
/**
* 初始化property对象
*/
private static void initProperty() {
/**
* 1、获取对象的名称
* 2、获取容器中的对象
* 3、遍历属性
* 4、将属性注入到对象中
* 5、判断ref属性是否为空
* 6、对属性值分别做处理:为属性值--》用包装类转换,
* 对应对象,直接获取其对应的对象
*/
try {
if (beanList.size()>0) {
for (Bean bean : beanList) {
String name = bean.getName();
Object object = map.get(name);
for (Property property : bean.getList()) {
String name1 = property.getName();
String value = property.getValue();
String ref = property.getRef();
Class<?> aClass = object.getClass();
Field field = null;
try {
field = aClass.getDeclaredField(name1);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
//set方法的拼接,首字母大写
String setterMethodName="set"+StringUtil.firstToUpperCase(name1);
Method declaredMethod = aClass.getDeclaredMethod(setterMethodName, field.getType());
if (ref==null){
Object objectValue = field.getType().getConstructor(String.class).newInstance(value);
declaredMethod.invoke(object,objectValue);
}else {
declaredMethod.invoke(object,map.get(ref));
}
}
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
/**
* 通过此方法获取对应的对象
* @param beanName
* @param tClass
* @param <T>
* @return
*/
public static <T> T getBean(String beanName,Class<T> tClass){
return (T) map.get(beanName);
}
//转化首字母大写
public static String firstToUpperCase(String name){
if (name == null || name.isEmpty()) {
return null;
}
return name.substring(0,1).toUpperCase()+name.substring(1);
}
6、通过反射封装JDBC结果集
/**
* JDBC查询结果集映射封装
*/
public class JDBCUtil {
private static Properties properties;
private static Connection connection;
private static String driver ;
private static String url ;
private static String username;
private static String password ;
static {
try {
/**
* 加载配置文件
*/
load();
/**
* 获取连接
*/
getConnect();
} catch (IOException e) {
System.out.println("加载配置文件异常");
e.printStackTrace();
} catch (SQLException e) {
System.out.println("sql语句错误");
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 无条件查询
* @param sql sql语句
* @param aClass1 映射的对象
* @param <T>
* @return
*/
public static <T> List<T> select(String sql,Class<T> aClass1){
List<T> result=null;
try {
if (sql!=null&&aClass1!=null){
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet resultSet; resultSet = preparedStatement.executeQuery();
result= getResult(resultSet, aClass1);
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
/**
* 单表条件查询
* @param sql sql语句
* @param aClass1 映射封装的对应的对象
* @param objects 条件参数
* @param <T>
* @return
*/
public static <T> List<T> select(String sql,Class<T> aClass1,Object[] objects){
List<T> list=null;
try {
if (sql!=null&&aClass1!=null){
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < objects.length; i++) {
preparedStatement.setObject(i+1,objects[i]);
}
ResultSet resultSet = preparedStatement.executeQuery();
list= getResult(resultSet, aClass1);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
/**
*将首字母转大写
* @param name
* @return
*/
public static String setGetter(String name){
String newName="";
if (name!=null){
newName = name.substring(0,1).toUpperCase()+name.substring(1);
}
return newName;
}
/**
* 加载配置文件
* @throws IOException
*/
private static void load() throws IOException {
properties = new Properties();
InputStream inputStream = Object.class.getResourceAsStream("/db.properties");
properties.load(inputStream);
driver = properties.getProperty("mysql.driver");
url = properties.getProperty("mysql.url");
username = properties.getProperty("mysql.username");
password = properties.getProperty("mysql.password");
}
/**
* 建立连接
* @throws ClassNotFoundException
* @throws SQLException
*/
private static void getConnect() throws ClassNotFoundException, SQLException {
Class<?> aClass = Class.forName(driver);
connection = DriverManager.getConnection(url, username, password);
}
/**
* 结果集的封装
* @param resultSet 传入查询的结果集
* @param aClass1 传入需要映射的类
* @param <T>
* @return
*/
private static <T>List<T> getResult(ResultSet resultSet ,Class<T> aClass1){
List<T> list= null;
try {
list = new ArrayList<>();
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
while (resultSet.next()){
Object o = aClass1.getConstructor().newInstance();
for (int i = 1; i <=columnCount ; i++) {
//属性名
String catalogName = metaData.getColumnName(i);
//属性值
String resultValue = resultSet.getString(i);
//System.out.println(catalogName+"-->"+resultValue);
Field field = aClass1.getDeclaredField(catalogName);
Object value = field.getType().getConstructor(String.class).newInstance(resultValue);
Method method = aClass1.getDeclaredMethod("set"+setGetter(catalogName), field.getType());
method.invoke(o,value);
}
list.add((T)o);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return list;
}
}