简单模拟下ssm,复习动态代理

最近在学ssm,好奇底层是怎么实现的

就根据现在所学的模拟了个,

顺便复习下动态代理,

时间紧,写的略渣

lib

dom4j-1.61.jar

xml

my.xml












play.xml











用来模拟ioc根据配置文件创建对象

people.java

public interface People {
	public void eat(User u);
	public void sleep(User u);
	
}

用来模拟动态代理根据配置文件实现mapper接口

User.java

public class User {
private String name;
private int age;
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public int getAge() {
	return age;
}
public void setAge(int age) {
	this.age = age;
}
public String toString() {
	return "user [name=" + name + ", age=" + age + "]";
}

}


main

 
  
import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class Test   {     public static void main(String[] args) throws Exception {         //模拟ioc,根据配置文件实例化对象          User u = newBean("xml/my.xml","lihua");                  //模拟动态代理实现dao接口//只是纯接口的动态代理没加jdbc                  People daili = (People)daili("xml/play.xml",People.class);                 daili.sleep(u);         daili.eat(u);     }          /**      * bean传给service根据 xml配置的事件动态代理dao接口      * @param path 配置文件地址      * @param c 需要代理的接口      * @return 代理实现的类      * @throws DocumentException      */     private static Object daili(String path,Class c) throws DocumentException {//代理类         SAXReader reader = new SAXReader();         Document document = reader.read(new File(path));//参数1:配置文件位置         Element element = document.getRootElement();         List elements = element.elements("play");         final Map> map=new HashMap();//这里先遍历配置文件储存,因为用集合取数据方便,也可以边读接口边根据xml实现接口                 Map ma=null;         for (Element pl : elements) {             ma=new HashMap();             String name = pl.attributeValue("id");//方法名             List para = pl.elements("property");             for (Element p : para) {                 String value = p.attributeValue("value");//参数值的string状态                 String type = p.attributeValue("type");//参数类型的类                 ma.put(value, type);             }             map.put(name, ma);                      } InvocationHandler h =new InvocationHandler() {                  public Object invoke(Object proxy, Method method, Object[] args)                 throws Throwable {             String name = method.getName();                             User u=(User)args[0];         Set>> set = map.entrySet();         for(Entry> entry:set){             if(entry.getKey().equals(name)&&name.contains("sleep")){                 Set> value = entry.getValue().entrySet();                 for (Entry v: value) {                     String para = v.getKey();//依次取出参数,这里只有一个就不判断了                     String type = v.getValue();//因为直接打印就不转换回去了,需要的话自行转换                     System.out.println(u.getName()+"今年"+u.getAge()+"岁,一天睡"+para);                 }                              }             if(entry.getKey().equals(name)&&name.contains("eat")){                 Set> value = entry.getValue().entrySet();                 for (Entry v: value) {                     String para = v.getKey();//依次取出参数,这里只有一个就不判断了                     String type = v.getValue();//因为直接打印就不转换回去了,需要的话自行转换                     System.out.println(u.getName()+"今年"+u.getAge()+"岁,喜欢吃"+para);                 }                              }         }                  return null;                  } };         return Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{c}, h);     } /**  * 通过xml配置的id来实例化一个对象  * @param path xml位置  * @param id xml中的id  * @return 实例化好的bean对象  * @throws Exception  */     private static User newBean(String path,String id) throws Exception {         SAXReader reader = new SAXReader();         Document document = reader.read(new File(path));//参数1:配置文件位置         Element element = document.getRootElement();         List peoples = element.elements("people");         Element people=null;         for (Element peo : peoples) {             if(peo.attributeValue("id").equals(id))//参数1:id             people=peo;         }         if(people==null){             System.out.println("配置文件中无此id");             System.exit(0);         }         List attrs = people.elements("property");         Class user = Class.forName("dydaili.User");         Method[] methods = user.getMethods();         Map[]> map=new HashMap();         for (Method method : methods) {//获取bean的所有方法和参数类型             String name = method.getName();             Class[] parameters = method.getParameterTypes();             map.put(name, parameters);         }//后面有解释         User u=(dydaili.User) user.newInstance();         for (Element attr : attrs) {             String name = attr.attributeValue("name");//属性名             String value = attr.attributeValue("value");//属性的值             String type =attr.attributeValue("type");//属性类型             Constructor c1 = Class.forName(type).getDeclaredConstructor(String.class);//获取常用类型构造,把string转换为对应类型                          Method method = user.getMethod("set"+name,map.get("set"+name));//获取set方法,不用 Class.forName(type)而用map.get("set"+name)可以避免int和integer不匹配而找不到方法                          method.invoke(u, c1.newInstance(value));         }         return u;     } }

难点在反射实例化类时,set方法是int型而配置文件是integer,于是找不到set方法,只好先获取了所有方法信息,只根据方法名去找方法,配置文件给的类型只用来转换值的类型


你可能感兴趣的:(java)