java反射与内省
反射
通过程序运行时信息来获取类或对象的类信息
获取Class对象的三种方法
Class class = dog.getCalss();
Class class = Dog.class;
Class class = Class.forName("com.vince.Dog");//会有ClassNotFoundExeception
通过反射实例化对象和获取对象信息
package reflection;
import java.lang.reflect.*;
public class ReflectionDemo {
public static void main(String[] args) {
Dog dog = new Dog("dabao",5,"白色","藏獒");
Class dogClass = dog.getClass();
//通过反射实例化对象
try {
//Dog inflectDog = (Dog)dogClass.newInstance("dwr");//jdk1.9之后不推荐使用
Dog inflectDog = (Dog)dogClass.getDeclaredConstructor(String.class, int.class, String.class, String.class).newInstance("xiaobai",3,"黑色","咖啡毛");
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//获取构造方法
Constructor[] constructors = dogClass.getConstructors();//获取所有构造方法
for (int i = 0; i < constructors.length; i++) {
System.out.println(constructors[i].getName());//构造参数名
System.out.println(constructors[i].getParameterCount());//参数数目
}
try {
Constructor constructor = dogClass.getConstructor(String.class, int.class, String.class, String.class);//根据变量类型获取指定的构造方法
//之后就可以调用上面的newInstance方法实例化一个对象
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//获取类中的所有属性
Field[] fields = dogClass.getFields();//获取所有非private的属性
System.out.println(fields.length);
Field[] declaredFields = dogClass.getDeclaredFields();//获取所有属性
System.out.println(declaredFields.length);
for (int i = 0; i < declaredFields.length; i++) {
int modifiers = declaredFields[i].getModifiers();
System.out.println(Modifier.toString(modifiers)+" "+declaredFields[i].getType()+" "+declaredFields[i].getName());
}
//获取包对象的包信息
Package aPackage = dogClass.getPackage();
System.out.println(aPackage.getName());
//获取方法
//获取所有非private方法,包括父类的方法
Method[] methods = dogClass.getMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
if(methods[i].getName().equals("toString")){
try {
String s = (String)methods[i].invoke(dog);//调用方法
System.out.println(s);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
System.out.println("-------------");
//获取当前类的所有方法(包括private),不包括父类
Method[] methods1 = dogClass.getDeclaredMethods();
for (int i = 0; i < methods1.length; i++) {
System.out.println(methods1[i]);
if(methods1[i].getName().equals("set")){
//设置私有方法可以被访问(去除访问修饰符的检查)
methods1[i].setAccessible(true);
try {
methods1[i].invoke(dog);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
内省
Java中提供的一套用来访问某个属性的getter/setter方法的API
读取配置文件案例
package instrospector;
//配置类
public class Config {
private String username;
private String password;
private String url;
public String getUsername() {
return username;
}
public void setUsername(String name) {
this.username = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "Config{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", url='" + url + '\'' +
'}';
}
}
//配置文件config.properties
bean.name= instrospector.Config
bean.username = hello
bean.password = 123
bean.url = http://www.xiaoming.net.cn
package instrospector;
//读取配置文件的工厂
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class BeanFactory {
private static Properties prop = new Properties();
//使用静态代码块读取配置文件
static{
InputStream in = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("instrospector/config.properties");
try {
prop.load(in);//加载文件
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取一个Bean
* @param name
* @return
*/
public static Object getBean(String name){
Object bean = null;
String beanName = prop.getProperty(name);
try {
Class<?> aClass = Class.forName(beanName);
bean = aClass.getDeclaredConstructor().newInstance();
//通过类信息获取javaBean的描述信息
BeanInfo beanInfo = Introspector.getBeanInfo(aClass);
//通过javaBean的描述信息,获取该类的所有属性描述器
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (int i = 0; i < propertyDescriptors.length; i++) {
//获取属性名
String propertyName = propertyDescriptors[i].getName();
//获取某个属性的写方法
Method writeMethod = propertyDescriptors[i].getWriteMethod();
if("username".equals(propertyName)){
writeMethod.invoke(bean,prop.getProperty("bean.username"));
}else if("password".equals(propertyName)){
writeMethod.invoke(bean,prop.getProperty("bean.password"));
}else if("url".equals(propertyName)){
writeMethod.invoke(bean,prop.getProperty("bean.url"));
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return bean;
}
}
package instrospector;
//测试
public class BeanTest {
public static void main(String[] args) {
Config bean = (Config)BeanFactory.getBean("bean.name");
System.out.println(bean);
}
}
AOP编程
面向切面编程,将一些与业务代码无关的代码放在另外的一个地方,让业务代码执行的时候跟着执行
//业务接口
public interface IManager {
public void add(String item);
}
import java.util.ArrayList;
//业务内容
public class IManagerImpl implements IManager{
private ArrayList<String> list = new ArrayList<>();
@Override
public void add(String item) {
list.add(item);
}
}
//通知(切面内容)
public interface Advice {
public void beforeAdvice();
public void afterAdvice();
}
//切面内容实现类
public class LogAdvice implements Advice{
@Override
public void beforeAdvice() {
System.out.println("start time:"+System.currentTimeMillis());
}
@Override
public void afterAdvice() {
System.out.println("end time:"+System.currentTimeMillis());
}
}
//配置文件
bean.target = aop.IManagerImpl
bean.advice = aop.LogAdvice
bean = aop.ProxyFactoryBean
//动态代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactoryBean implements InvocationHandler {
private Object target;//业务对象
private Advice advice;//切面对象
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
/**
* 获取代理对象
*/
public Object getProxy(){
Object proxy = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
return proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
advice.beforeAdvice();
Object object = method.invoke(target,args);
advice.afterAdvice();
return object;
}
}
//代理类的处理加工工厂
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class BeanFactory {
private Properties prop = new Properties();
//读取配置文件
public BeanFactory(InputStream in){
try {
prop.load(in);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取一个bean实例
* @param name
* @return
*/
public Object getBean(String name){
String className = prop.getProperty(name);
Object bean = null;
try {
//获取ProxyFactoryBean的class对象
Class<?> aClass = Class.forName(className);//创建一个代理类
bean = aClass.getDeclaredConstructor().newInstance();
//根据配置文件实例化target,advice对象
Object target = Class.forName(prop.getProperty(name+".target")).getDeclaredConstructor().newInstance();
Object advice = Class.forName(prop.getProperty(name+".advice")).getDeclaredConstructor().newInstance();
//通过内省获取代理类属性信息
BeanInfo beanInfo = Introspector.getBeanInfo(aClass);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for(PropertyDescriptor pd:propertyDescriptors){
String propertyName = pd.getName();
Method writeMethod = pd.getWriteMethod();
if("target".equals(propertyName)){
writeMethod.invoke(bean,target);
}else if("advice".equals(propertyName)){
writeMethod.invoke(bean,advice);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IntrospectionException e) {
e.printStackTrace();
}
return bean;
}
}
//测试
import java.io.InputStream;
public class AOPTest {
public static void main(String[] args) {
//读取配置文件
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("aop/bean.properties");
//创建Bean的工厂对象
BeanFactory beanFactory = new BeanFactory(in);
//获取代理对象
ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)beanFactory.getBean("bean");
IManager proxy = (IManager) proxyFactoryBean.getProxy();//反射得到的代理实例
proxy.add("我是一只猫");
}
}