Spring注解原理学习(自己编写例子)-2

来源:互联网 发布:易语言web服务器源码 编辑:程序博客网 时间:2024/06/05 09:08
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://www.springframework.org/schema/beans             http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"><bean id = "injectTestDao" class="test.Inject.InjectTestDao" /><bean id = "injectTestService" class = "test.Inject.InjectTestServiceImpl" /></beans>


Bean定义类:
package test.Inject;import java.util.ArrayList;import java.util.List;/** * xml中的<bean/>的定义 * @author Administrator * */public class BeanDefinition{private String id;private String clazz;private List<PropertyDefinition> propertyDefinitions=new ArrayList<PropertyDefinition>();public BeanDefinition(String id, String clazz) {super();this.id = id;this.clazz = clazz;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getClazz() {return clazz;}public void setClazz(String clazz) {this.clazz = clazz;}public List<PropertyDefinition> getPropertyDefinitions() {return propertyDefinitions;}public void setPropertyDefinitions(List<PropertyDefinition> propertyDefinitions) {this.propertyDefinitions = propertyDefinitions;}}

Property定义类用于读取 <bean><property>

package test.Inject;public class PropertyDefinition {private String name;private String ref;private String value;public PropertyDefinition(String name, String ref,String value) {super();this.name = name;this.ref = ref;this.value=value;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getRef() {return ref;}public void setRef(String ref) {this.ref = ref;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}}


注释类:

package test.Inject;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/*** @Target 表示该注解用于什么地方,可能的 ElemenetType 参数包括: * ElemenetType.CONSTRUCTOR 构造器声明 * ElemenetType.FIELD 域声明(包括 enum 实例) * ElemenetType.LOCAL_VARIABLE 局部变量声明 * ElemenetType.METHOD 方法声明 * ElemenetType.PACKAGE 包声明 * ElemenetType.PARAMETER 参数声明 * ElemenetType.TYPE 类,接口(包括注解类型)或enum声明 * * @Retention 表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括: * RetentionPolicy.SOURCE 注解将被编译器丢弃 * RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃 * RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信* 息。 * * @Documented 将此注解包含在 javadoc 中 * @Inherited 允许子类继承父类中的注解**/// 在运行时执行@Retention(RetentionPolicy.RUNTIME)// 注解适用地方(字段和方法)@Target({ ElementType.FIELD, ElementType.METHOD })public @interface LwxResource {//注解的name属性  @LwxResource(name="dddd")public String name() default "";}

要注入的类:
package test.Inject;/** * @Description: 要注入的Dao类 * @ClassName: InjectTestDao * @Project: spring-aop */public class InjectTestDao {public void show(){System.out.println("这里是dao方法........");}}


带有注释的类:

package test.Inject;/** * @Description: 带有注解的服务 * @ClassName: InjectTestServiceImpl * @Project: spring-aop * @Author: lwx */public class InjectTestServiceImpl {// 字段上的注解,可以配置name属性@LwxResourcepublic InjectTestDao injectTestDao;//// set方法上的注解,带有name属性//@LwxResource(name = "injectTestDao")//public void setInjectTestDao(InjectTestDao injectTestDao) {//this.injectTestDao = injectTestDao;//}public void show() {injectTestDao.show();System.out.println("这里是Service方法........");}}


注释处理类
package test.Inject;import java.beans.IntrospectionException;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.commons.beanutils.ConvertUtils;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.XPath;import org.dom4j.io.SAXReader;/** * 自定义容器 *  * @author Administrator *  */public class UserDefinedClassPathXMLApplicationContext {private List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();private Map<String, Object> sigletons = new HashMap<String, Object>();public UserDefinedClassPathXMLApplicationContext(String filename) {this.readXML(filename);this.instanceBeans();this.annotationInject();this.injectObject();}/** * 读取xml配置文件 *  * @param filename */@SuppressWarnings("all")private void readXML(String filename) {SAXReader saxReader = new SAXReader();Document document = null;try {URL xmlPath = this.getClass().getClassLoader().getResource(filename);document = saxReader.read(xmlPath);XPath xPath = document.createXPath("//ns:beans/ns:bean");// 创建beans/bean查询路径。从根路径开始Map<String, String> nsMap = new HashMap<String, String>();nsMap.put("ns", "http://www.springframework.org/schema/beans");// 加入命名空间xPath.setNamespaceURIs(nsMap);// 设置命名空间List<Element> beans = xPath.selectNodes(document);// 获取文档下所有bean节点for (Element element : beans) {String id = element.attributeValue("id");String clazz = element.attributeValue("class");BeanDefinition beanDefinition = new BeanDefinition(id, clazz);XPath xPath2 = element.createXPath("ns:property");// 从相对路径开始xPath2.setNamespaceURIs(nsMap);List<Element> propertys = xPath2.selectNodes(element);for (Element element2 : propertys) {String name = element2.attributeValue("name");String ref = element2.attributeValue("ref");String value = element2.attributeValue("value");PropertyDefinition propertyDefinition = new PropertyDefinition(name, ref, value);beanDefinition.getPropertyDefinitions().add(propertyDefinition);}beanDefinitions.add(beanDefinition);}} catch (DocumentException e) {e.printStackTrace();}}/** * 完成bean的实例化 */private void instanceBeans() {try {for (BeanDefinition beanDefinition : beanDefinitions) {if (beanDefinition.getClazz() != null&& !"".equals(beanDefinition.getClazz().trim())) {sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClazz()).newInstance());}}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}/** * 为bean对象的属性注入值 *  * @throws IntrospectionException * @throws InvocationTargetException * @throws IllegalAccessException * @throws IllegalArgumentException */private void injectObject() {try {for (BeanDefinition beanDefinition : beanDefinitions) {Object bean = sigletons.get(beanDefinition.getId());if (bean != null) {PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();for (PropertyDefinition propertyDefinition : beanDefinition.getPropertyDefinitions()) {for (PropertyDescriptor propertyDescriptor : ps) {if (propertyDefinition.getName().equals(propertyDescriptor.getName())) {Method setterMethod = propertyDescriptor.getWriteMethod();// 获取属性的setter方法if (setterMethod != null) {Object temp = null;if (propertyDefinition.getRef() != null&& !"".equals(propertyDefinition.getRef().trim())) {temp = sigletons.get(propertyDefinition.getRef());} else if (propertyDefinition.getValue() != null&& !"".equals(propertyDefinition.getValue().trim())) {temp = ConvertUtils.convert(propertyDefinition.getValue(),propertyDescriptor.getPropertyType());}setterMethod.setAccessible(true);// 防止setter方法为privatesetterMethod.invoke(bean, temp);// 把引用对象注入到属性}break;}}}}}} catch (Exception e) {e.printStackTrace();}}/** * 通过注解实现注入依赖对象 *  * @throws IntrospectionException * @throws InvocationTargetException * @throws IllegalAccessException * @throws IllegalArgumentException */private void annotationInject() {try {for (String beanName : sigletons.keySet()) {Object bean = sigletons.get(beanName);if (bean != null) {PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();for (PropertyDescriptor propertyDescriptor : ps) {Method setterMethod = propertyDescriptor.getWriteMethod();if (setterMethod != null&& setterMethod.isAnnotationPresent(LwxResource.class)) {LwxResource userDefinedResource = setterMethod.getAnnotation(LwxResource.class);Object temp = null;if (userDefinedResource.name() != null&& !"".equals(userDefinedResource.name())) {// 一旦指定了name属性,就只能按名称装配了temp = sigletons.get(userDefinedResource.name());} else {temp = sigletons.get(propertyDescriptor.getName());if (temp == null) {for (String key : sigletons.keySet()) {if (propertyDescriptor.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())) {temp = sigletons.get(key);break;}}}}setterMethod.setAccessible(true);setterMethod.invoke(bean, temp);// 把引用对象注入到属性}}Field[] fields = bean.getClass().getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(LwxResource.class)) {LwxResource userDefinedResource = field.getAnnotation(LwxResource.class);Object temp = null;if (userDefinedResource.name() != null&& !"".equals(userDefinedResource.name())) {temp = sigletons.get(userDefinedResource.name());} else {System.out.println(field.getName());temp = sigletons.get(field.getName());if (temp == null) {for (String key : sigletons.keySet()) {if (field.getType().isAssignableFrom(sigletons.get(key).getClass())) {temp = sigletons.get(key);break;}}}}field.setAccessible(true);// 允许访问private字段field.set(bean, temp);}}}}} catch (Exception e) {e.printStackTrace();}}/** * 获取bean实例 *  * @param beanName * @return */public Object getBean(String beanName) {return this.sigletons.get(beanName);}public static void main(String[] args) {//读文件的地址是从src下开始读的 也就是 src\test\Inject\injectTest.xml地址UserDefinedClassPathXMLApplicationContext applicationContext = new UserDefinedClassPathXMLApplicationContext("test\\Inject\\injectTest.xml");InjectTestServiceImpl injectTestService = (InjectTestServiceImpl) applicationContext.getBean("injectTestService");injectTestService.show();}}
0 0
原创粉丝点击