JAVA学习日志3-4(Spring IoC)

Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架
在这里插入图片描述
IoC控制反转,当A类依赖B类时(A类需要B类的实例化对象)在没有控制反转前需要A类主动去创建B类的对象(new B类对象)。控制反转后,B类在初始化之前,B类所需要的对象就由容器创建好了并存储在容器中,当B类需要使用A类的对象时再由容器传递给B类。可以降低程序之间的耦合度。

  • 降低耦合度的方法
    1.通过反射来加载要实例化的类
    2.把完整的包名+类名放入到配置文件 xml
    手写一个简单的ioc
    如test依赖service,sercice依赖dao
    先把需要使用到的对象记录在一个文件里,test使用service的对象,service使用dao的对象
    在这里插入图片描述
    定义一个工厂,其实是一个容器,把需要使用到的对象都放到这个容器里,当有对象使用的需求时直接从容器里取
public class Factory {
    private static Map<String,Object> map;

    static {
        try {
        //把记录需要使用的类的文件加载进来
            InputStream is  = Class.forName("com.fyj.factory.Factory").getClassLoader().getResourceAsStream("IocConfig.properties");
            Properties properties = new Properties();
            properties.load(is);
            //用map作为容器存储每个对象
            map = new HashMap<String, Object>();
            Enumeration enumeration = properties.keys();
            while (enumeration.hasMoreElements()){
                String key = (String) enumeration.nextElement();
                String val = properties.getProperty(key);
                //通过反射实例化对象
                Object object = Class.forName(val).newInstance();
                map.put(key,object);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

//取出对象
    public static Object get(String key){
        return map.get(key);
    }

}

dao无需实例化对象

public class IocTestDaoImpl implements IocTestDao {
    public void show() {
        System.out.println("yes");
    }
}

service需要实例化dao的对象,所以从factory中取出dao的实例对象

public class IocTestServiceImpl implements IocTestService {
    public void show() {
        IocTestDaoImpl iocTestDao = (IocTestDaoImpl)Factory.get("dao");
        iocTestDao.show();
    }
}

test需要service的对象,从factory中取

public class IocTest {
    @Test
    public void Test1(){
        IocTestServiceImpl iocTestService = (IocTestServiceImpl)Factory.get("service");
        iocTestService.show();
    }
}

spring IOC

  • spring IOC使用的小案例
    1.pom文件中添加依赖
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
public class Factory {
    public  TestClass getTestClass(){
        return  new TestClass(2);
    }
}

2.编写xml文件,即需要使用到的实例化的类都写到里面

<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">
        <!--    实例化名为Factory对象时,会使用Factory的无参构造-->
    <bean id="Factory1" class="Factory" ></bean>
    <!--    实例化名为Factory1的对象,并使用getTestClass方法,getTestClass实例化出TestClass对象-->
    <bean id="TestClassByFac"  factory-bean="Factory1" factory-method="getTestClass"></bean>
</beans>

3.使用

public class Test {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("config.xml");
        Factory factory = (Factory) app.getBean("Factory1");
        TestClass r = app.getBean("TestClassByFac",TestClass.class);
        r.show();
    }
}
  • 相关API
    BeanFactory 是spring的顶级父类,提供了一些spring IO的基础代码,我们使用的是其派生接口 ApplicationContext
    ApplicationContext 其实就是对 BeanFactory 封装以及加强(ioc 的代码有封装,日志的处理都有相关的封装 )

    • BeanFactory和ApplicationContext 区别
      ApplicationContext 采用的是立即加载来创建对象 也就是spring容器初始化 创建spring管理的所有的对象 (单例) ,BeanFactory (多例) 使用的是延迟加载的方式来创建对象 在具体使用的时候由容器创建对象

    • ApplicationContext的3个实现类

    类名作用
    ClassPathXmlApplicationContext通过类路径来加载配置文件
    FileSystemXmlApplicationContext根据(绝对路径)路径来加载配置文件
    AnnotationConfigApplicationContext使用注解的方式来加载配置文件
  • spring对bean的管理
    spring提供了scope属性来对bean的属性进行设置

属性-
singleton单例
prototype多例
request用在web项目,对象存放容器中,并且放到request 作用域中
session用在web项目,对象存放容器中,并且放到session作用域中
globaisession在 web的分布式项目,存在全局的session中

spring的依赖注入
依赖注入,获取到具有指定参数的对象,依赖注入两种方式:构造方法、set 注入

    <bean id="stu" class="com.fyj.bean.Student">
        <constructor-arg name="uid" value="1"></constructor-arg>
        <constructor-arg name="uname" value="lisi"></constructor-arg>
        <constructor-arg name="upwd" value="123"></constructor-arg>
        <constructor-arg name="usex" value="男"></constructor-arg>
    </bean>
    
    <bean id="stu0" class="com.fyj.bean.Student">
        <property name="uid" value="2"></property>
        <property name="usex" value="女"></property>
    </bean>

property用于set注入,set注入是根据属性的set方法来进行赋值的,name需要和set方法所指的名称保持一致,如类中的方法setUpwd() 和 name=Upwd 对应
constructor用于构造方法注入name名称和构造方法中参数的名称一致,构造方法注入时,参数个数需要和构造方法中的个数相同。
当需要注入引用数据的类型时,需要先获得其实体Bean在通过id注入,注入时使用ref而非value,如给Date类的成员变量赋值

    <bean id="date" class="java.util.Date"></bean>
    <bean id="stu0" class="com.fyj.bean.Student">
        <property name="date" ref="date"></property>
    </bean>

set注入的另一种形式是使用p标签,如下

    <bean id="date" class="java.util.Date"></bean>
    <bean id="stu0" class="com.fyj.bean.Student" p:usex="男" p:date-ref="date"></bean>

使用时可以通过ApplicationContext 根据bean的id来获取对象

        ApplicationContext app = new ClassPathXmlApplicationContext("config.xml");
        User user = app.getBean("stu0",Student.class);

注入集合相关的数据

    <bean id="stu0" class="com.fyj.bean.Student">
        <property name="array">
            <array>
                <value>1</value>
                <value>2</value>
            </array>
        </property>

        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>

        <property name="map">
            <map>
                <entry key="a" value="1"></entry>
                <entry key="b" value="2"></entry>
            </map>
        </property>
        
        <property name="properties">
            <props>
                <prop key="a">1</prop>
                <prop key="b">2</prop>
            </props>
        </property>
    </bean>

配置文件模块化
多个配置信息写在一个xml文件中时结构清晰度较差,可以设置一个主要的xml文件,在这个xml文件中引入其他的xml文件。如

<import resource="classpath:User.xml" ></import>

注意:当主文件中的bean的id,和被引入的文件中的bean的id重名时,主文件的bean会覆盖背引入文件的bean

通过注解进行依赖注入

  • 步骤
    1.需要先在pom文件中添加依赖

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.2.RELEASE</version>
       </dependency>
    

    2.配置文件的dtd约束为

<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">

扫描包下的注解,及其子包

    <context:component-scan base-package="com.fyj"/>

在这里插入图片描述
3.添加注解
@Component 用来实例化对象,把当前对象给spring来进行管理(在类上进行修饰),有一个value属性,默认值是当前类的(首字母小写)名称
@Repository @Service @Controller 三者和 @Component 功能完全相同,分别用于持久层、业务层、视图层
在这里插入图片描述
在这里插入图片描述
@Autowired 用来给对象中的类进行注入,一般使用的时候在成员变量上。注入时是案类型注入,当spring中有多个匹配的类时,就会报错。可以添加@Qualifier来指定名称进行注入。
在这里插入图片描述
使用时还是通过app.getBean获取bean来使用
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值