Spring框架学习(一):工厂设计模式、学习前准备

1.工厂设计模式

1.1 简单工厂

设计核心(工厂)

public class BeanFactory {
    /*
    class Properties extends Hashtable<Object,Object>   继承于hashtable
     */
    //创建一个Properties集合
    private static Properties env =  new Properties();
    //使用静态代码块保证Properties只创建一次
    static {
        try {
            //1.获得文件输入流
            InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");

            //2.将文件内容读入env中
            //load()    从输入字节流中读取属性列表(键和元素对)
            env.load(inputStream);

            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
    对象创建方式:
        1.使用构造器创建对象
        2.使用反射创建对象(解耦合)
     */
    public static UserService getUserService(){
        //return new UserServiceImpl();
        UserService userService = null;
        try {
            //Class<?> clazz = Class.forName("com.xxc.basic.UserServiceImpl");
            Class<?> clazz = Class.forName(env.getProperty("userServices"));
            userService = (UserService)clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userService;
    }

    public static UserDAO getUserDAO(){
        UserDAO userDAO = null;
        try {
			//Class<?> clazz = Class.forName("com.xxc.basic.UserDAOImpl");
            Class<?> clazz = Class.forName(env.getProperty("userDAO"));
            userDAO = (UserDAO)clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userDAO;
    }
}

UserService接口

public interface UserService {
    void register(User user);
    void login(String name,String password);
}

UserService具体实现类

使用工厂解耦合

public class UserServiceImpl implements UserService {
    //private UserDAO userDAO = new UserDAOImpl();
    private UserDAO userDAO = BeanFactory.getUserDAO();

    @Override
    public void register(User user) {
        userDAO.save(user);
    }

    @Override
    public void login(String name, String password) {
        userDAO.queryUserByNameAndPassword(name, password);
    }
}

UserDAO接口

public interface UserDAO {
    void save(User user);
    void queryUserByNameAndPassword(String name,String password);
}

UserDAO接口的实现类

public class UserDAOImpl implements UserDAO{
    @Override
    public void save(User user) {
        System.out.println("insert into user = "+user);
    }

    @Override
    public void queryUserByNameAndPassword(String name, String password) {
        System.out.println("query User name = "+name+" password = "+password);
    }
}

测试方法

@Test
public void Test01(){
    //UserService userService = new UserServiceImpl();

    //使用工厂模式解耦合
    UserService userService = BeanFactory.getUserService();
    userService.login("name","xxc");
    User user = new User("xxc", "123456");
    userService.register(user);
}

配置文件applicationContext.properties

# properties集合存储文件内容
# 是一种特殊的Map key=String value=String

userServices = com.xxc.basic.UserServiceImpl
userDAO = com.xxc.basic.UserDAOImpl
1.2通用工厂

反思:

工厂方法中getUserService()和getUserDAO()中代码存在大量冗余,只有返回值类型,forname()中内容不同

因此就可以抽离出以下通用代码

public static Object getBean(String key){//key就是小配置文件中的key值
    Object o = null;
    try {
        Class<?> clazz = Class.forName(env.getProperty(key));
        o = clazz.newInstance();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return o;
}
1.3通用工厂的使用方式
1. 定义类
2. 通过配置文件告知工厂想要创建那个对象(application.properties)
	key = value
3. 通过工厂获得类的对象
	BeanFactory.getBean("key");

例:

1. 创建类
public class Person {}

3.使用
    @Test
    public void Test02(){
        Person person = (Person)BeanFactory.getBean("person");
        System.out.println(person);
    }
#2. 在配置文件中添加
person = com.xxc.basic.Person

2.第一个Spring程序

1.下载网址

www.spring.com

maven环境搭建

  • spring的jar包

maven下载地址:https://mvnrepository.com/search?q=spring

# 设置pom依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.4.RELEASE</version>
</dependency>
  • spring的配置文件
1. 配置文件放置位置:任意位置,没有硬性要求
2. 命名:没有硬性要求,建议:applicationContext.xml

在应用spring时,需要进行配置文件路径配置
2.spring的核心api

ApplicationContext

好处: 使用spring提供的ApplicationContext工厂创建对象,用于解耦合

ApplicationContext接口类型

屏蔽接口实现的差异
非web环境下:ClassPathXmlApplicationContext
web环境:XmlWebApplicationContext

重量级资源

ApplicationContext工厂的对象会占用大量资源
因此不会频繁创建,即一个应用只会创建一个工厂对象
所以也就要求ApplicationContext工厂一定是线程安全的,能够支持多线程访问
3.程序开发
1. 创建类型
2. 配置文件配置
3. 通过工厂类获得对象

ApplicationConText ctx = new ClassPathXmlApplicationContext("/application.xml");
Person person = (Person)ctx.getBean("person");
4.细节分析

spring工厂的相关方法

    @Test
    public void Test04() {
        //1.获得spring工厂对象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        //2、通过工厂获得对象
        //Person person = ctx.getBean("person", Person.class);

/*
        //使用这种方式创建时,需要注意,applicationContext.xml需要保证在配置文件中,只能有一个bean中class是Person
        Person person = ctx.getBean(Person.class);
        System.out.println(person);
*/

        //返回此工厂定义的所有bean名称(<bean id="">id后引号中的值)
        //String[] names = ctx.getBeanDefinitionNames();

        //返回此工厂中给定类型的名称
//        String[] names = ctx.getBeanNamesForType(Person.class);
//        for (String name : names) {
//            System.out.println(name);
//        }

        //判断是否存在指定id的bean,存在返回true
//        boolean person = ctx.containsBeanDefinition("a");

        //判断是否存在指定id的bean
        boolean person = ctx.containsBean("person");
        System.out.println(person);

    }

配置文件中需要注意的细节

1. 只配置class标签
<bean class = ""/>
a) 使用上面这种配置有没有id值?
com.xxc.basic.User#0
b) 应用场景: 如果这个bean只使用一次,那么就可以省略id值
		    如果这个bean只使用多次,或者被其他bean引用则需要设置id值
		    
2. name属性
作用:用于在spring的配置文件中,为bean对象设置别名
id与name对比:
相同:
	1.ctx.getBean("id/name");
	2.<bean id="" class=""
		等效
	  <bean name="" class=""
区别:
	1.别名可以定义多个,但是id属性只能定义一个
	2.XML的id属性值命名要求:必须以字母开头,后面跟字母,数字,下划线,连字符,不能以特殊字符开头
		   name属性的值,没有命名要求
	  name属性会应用于特殊场景
	  不过XML发展到今天,就没有了这些限制
	3.代码区别
	  containBean可以用来判断id,也能判断name
	  containBeanDefintion可以用来判断id,但是不能用于判断name
5.spring工厂的底层实现原理(简易)

spring工厂是可以调用是由构造器的

简易原理

6.思考
问题:在开发过程中,是不是所有对象的创建都交给spring来管理?
回答:理论上是的,但是业存在特例:实体对象(entity)是不会交给spring来创建的,它是由持久层框架来创建的

3.spring 5.x与日志框架的整合

原因:spring与日志框架进行整合,日志框架就可以在控制台中,输出spring运行过程中一些重要信息
好处:便于了解spring框架的运行过程,便于程序调试
  • 如何整合
默认:
	spring1.2.3早期都是Commons-logging。jar
	spring5.x整合的是logback、log2j2
spring5.x整合log4j
	1.引入log4j.jar
	2.引入配置文件loj4j.properties

设置pom文件

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>

引入配置文件

# resources文件夹根目录下
### 配置根
log4j.rootLogger = debug,console

### 日志输出到控制台显示
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值