目录结构

批注 20200419 122203.jpg

利用properties配置文件实现简单的工厂模式

  • bean.properties
accountService=com.service.impl.AccountServiceImpl
accountDao=com.dao.impl.AccountDaoImpl
  • BeanFactory
    • 方法一(多例模式,不采用)
    /**
     * 根据Bean的名称获取bean对象
     *
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName) {
        Object bean = null;
        try {
            String beanPath = props.getProperty(beanName);
            System.out.println(beanPath);
            bean = Class.forName(beanPath).newInstance();//每次都会调用默认构造函数创建对象
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }
    
    • 方法二(单例)
    	public class BeanFactory {
        //定义一个Properties对象
        private static Properties props;
    
        //定义一个Map,用于存放我们要创建的对象。我们把它称之为容器
        private static Map<String, Object> beans;
    
        //使用静态代码块为Properties对象赋值
        static {
            try {
                //实例化对象
                props = new Properties();
                //获取properties文件的流对象
                InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
                props.load(in);
                //实例化容器
                beans = new HashMap<String, Object>();
                //取出配置文件中所有的Key
                Enumeration keys = props.keys();
                //遍历枚举
                while (keys.hasMoreElements()) {
                    //取出每个Key
                    String key = keys.nextElement().toString();
                    //根据key获取value
                    String beanPath = props.getProperty(key);
                    //反射创建对象
                    Object value = Class.forName(beanPath).newInstance();
                    //把key和value存入容器中
                    beans.put(key, value);
                }
            } catch (Exception e) {
                throw new ExceptionInInitializerError("初始化properties失败!");
            }
        }
    
        /**
         * 根据bean的名称获取对象
         *
         * @param beanName
         * @return
         */
        public static Object getBean(String beanName) {
            return beans.get(beanName);
        }
    	}
    

spring基于xml的快速demo

  • bean.xml
<?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.xsd">
    <!--把对象的创建交给spring来管理-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>

    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
</beans>
  • 实现
/**
 * 获取spring的IOC容器,并根据id获取对象
 * <p>
 * ApplicationContext的三个常用实现类:
 * ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下。不在的话,加载不了。(更常用)
 * FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有访问权限)
 * AnnotationConfigApplicationContext:它是用于读取注解创建容器
 *
 * 核心容器的两个接口引发出的问题:
 *  ApplicationContext:  单例对象适用
 *      它在构建核心容器时,创建对象采取的策略是采用立即加载的方式。也就是说,只要一读取完配置文件马上就创建配置文件中配置的对象。
 *
 *  BeanFactory:         多例对象使用
 *      它在构建核心容器时,创建对象采取的策略是采用延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。
 */
public class Client {

    public static void main(String[] args) {
        //1.获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //ApplicationContext ac = new FileSystemXmlApplicationContext("C:\\Users\\zhy\\Desktop\\bean.xml");
        //2.根据id获取对象
        IAccountService as = (IAccountService) ac.getBean("accountService");
        IAccountDao adao = ac.getBean("accountDao", IAccountDao.class);
        as.saveAccount();

        //*****************************
        //--------BeanFactory----------
//        Resource resource = new ClassPathResource("bean.xml");
//        BeanFactory factory = new XmlBeanFactory(resource);
//        IAccountService as  = (IAccountService)factory.getBean("accountService");
//        System.out.println(as);
    }

}

基于注解的快速demo

  • bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,
    而是一个名称为context名称空间和约束中-->
    <context:component-scan base-package="com"></context:component-scan>
</beans>
  • 常用IOC注解
    • 用于注入数据的(作用和在xml配置文件中的bean标签中的标签是一样的)

      • Autowired
        • 作用:自动按照类型注入。
          • 只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功
          • 如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
          • 如果Ioc容器中有多个类型匹配时:注入的变量名称需要与value相同
        • 出现位置:可以是变量上,也可以是方法上
        	@Autowired
        	IAccountDao accountDao1;
        
      • Qualifier
        • 作用:在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以
        • 属性:
          • value:用于指定注入bean的id。
        	@Autowired
        	@Qualifier(value = "accountDao2")
        	IAccountDao accountDao;
        
      • Resource
        • 作用:直接按照bean的id注入。它可以独立使用
        • 属性:
          • name:用于指定bean的id。
        	@Resource(name = "accountDao2")
        	IAccountDao accountDao;
        

      以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型 无法使用上述注解实现。
      另外,集合类型的注入只能通过XML来实现。

      • Value
        • 作用:用于注入基本类型和String类型的数据
        • 属性:
          • value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式) SpEL的写法:${表达式}
    • 用于改变作用范围的(和在bean标签中使用scope属性实现的功能是一样的)

      • Scope
        • 作用:用于指定bean的作用范围
        • 属性:
          • value:指定范围的取值。常用取值:singleton prototype
        	@Service("accountService")
        	@Scope("prototype")
        
    • 和生命周期有关的(和在bean标签中使用init-method和destroy-methode的作用是一样的)

      • PreDestroy(用于指定销毁方法)
      • PostConstruct(用于指定初始化方法)
          @PostConstruct
          public void init() {
              System.out.println("初始化方法执行了");
          }
      
          @PreDestroy
          public void destroy() {
              System.out.println("销毁方法执行了");
          }
      

hhhhh