Spring学习笔记1

一、初始Spring

1.作者

Rod Johnson(音乐和数学博士)。Expert One To One。这是Spring的前身。

2.概述

Spring是一个轻量级的DI/IoC和AOP容器框架,存在的目的是用于构建轻量级的J2EE应用。

Spring以一种非侵入式的方式管理你的代码,Spring提倡最少“侵入”,这也就意味着你可在适当的时候使用或者不用Spring

3.Spring的优势

Spring是一个轻量级的框架

更好的提供了事务的管理

更强大的框架支持、方便集成其他框架

低侵入、低耦合(降低组件之间的耦合度,实现软件各层之间的解耦)

4.构成

Spring体系图

二、IoC

1.引出IoC

修改前代码

Dao接口
public interface UserDao {

    public void getUser();

}
Dao实现
public class MySqlUserDaoImpl implements UserDao {

    @Override
    public void getUser() {
        System.out.println("mySql读取User数据。。。");
    }

}
public class OracleUserDaoImpl implements UserDao {

    @Override
    public void getUser() {
        System.out.println("Oracle读取User数据。。。");
    }

}
service
public class UserService {
    //UserDao dao = new MySqlUserDaoImpl();
    UserDao dao = new OracleUserDaoImpl();
    public void getUser(){
        dao.getUser();
    }
}

service层与dao层耦合度非常的高,层与层之间耦合度比较大,每次需求的变化都需要代码的修改。程序的灵活性很差。

修改代码后

Dao接口
public interface UserDao {

    public void getUser();

}
Dao实现
public class MySqlUserDaoImpl implements UserDao {

    @Override
    public void getUser() {
        System.out.println("mySql读取User数据。。。");
    }

}
public class OracleUserDaoImpl implements UserDao {

    @Override
    public void getUser() {
        System.out.println("Oracle读取User数据。。。");
    }

}
service
UserDao dao = null;
    public void getUser(){
        dao.getUser();
    }
    public void setDao(UserDao dao) {
        this.dao = dao;
}
Test
public static void main(String[] args) {
    UserService service = new UserService();
    service.setDao(new MySqlUserDaoImpl());
    service.getUser();

    System.out.println("--------------------");

    service.setDao(new OracleUserDaoImpl());
    service.getUser();
}

由以前的service主动创建对象变为现在的service被动接受对象。这种变化更好的分离了层与层之间的关系,同时降低了耦合度。
这种反转我们就可以成为控制反转。这种思想也就是IOC前身。

2.概述

不是一种技术,而是一种设计思想(类似于MVC)。就是原本在应用程序中我们手动创建对象的控制权,交由Spring框架管理,也就是创建对象的控制权反转到了Spring。

控制反转也称为依赖注入(Dependency Injection),其实控制反转和依赖注入是同一个概念,只是角度不同。

控制反转实际上涉及到两个行为,一个是控制,一个是反转。
控制:指由谁来创建对象
反转:指反过来了,由Spring创建对象,应用程序被动接受。以前应用程序是主动创建,现在应用程序被动接受。

3.事例

1).Vo类
public class User {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void show(){
        System.out.println("name :" + name);
    }
}
1).实现步骤

a、准备Jar包
b、创建配置文件

创建一个名为beans.xml的配置文件(配置文件的名称可以是其的)
拷贝文件头(xsd-configuration.html)
配置beans.xml

<bean id="user" class="cn.bdqn.vo.User">
<property name="name" value="Mike"></property>
</bean>

c、创建对象

public class Test {

    public static void main(String[] args) {
        //加载配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        //解析并实例化bean对象
        User user = (User)ac.getBean("user");
        //使用bean对象
        user.show();

    }
}

4.思考

1)、对象是谁创建的?

对象是由Spring创建的,具体的说应该是Spring中的BeanFactory创建的。

2)、对象的属性是怎么赋值的?

在创建Bean对象的同时,Spring就会自动将Property的属性值注入到Bean对象的属性上。

三、IoC容器和bean的创建时机

1.IoC容器

BeanFactory:这个接口是spring中最底层的接口,只提供了最简单的IoC功能(创建bean,获取bean,销毁bean)
在一般的应用当中,一般不使用BeanFactory;推荐用ApplicationContext(应用上下文);

ApplicationContext继承了BeanFactory,提供了基本的IoC功能;
ApplicationContext还提供了其他功能:

1,支持国际化;
2,支持消息机制;
3,支持统一的资源加载;
4,支持AOP功能;

2.bean的创建时机

1.用ApplicationContext创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("-------------------------------");
HelloWorld hello = ac.getBean("helloWorld",HelloWorld.class);
hello.show();

结果
这里写图片描述

2.用BeanFactory创建对象
Resource resource = new ClassPathResource("beans.xml");
BeanFactory bf = new XmlBeanFactory(resource);
System.out.println("-------------------------------");
HelloWorld hello = bf.getBean("helloWorld",HelloWorld.class);
hello.show();

结果
这里写图片描述

3.总结

1.ApplicationContext在加载的时候就会创建所有的bean (Web应用建议)
2.BeanFactory需要等到拿bean的时候才会创建bean(延迟初始化)(桌面程序)
3.使用applicationContext如何进行延迟初始化?

<bean id="helloWorld" class="cn.bdqn.vo.HelloWorld" lazy-init="default" />
lazy-init的取值有default、false、true。其中default、false和不写lazy-init作用相同都是不支持延迟初始化
针对于当前xml中所有的bean。<beans default-lazy-init="default | false | true">

四、bean的作用域、初始化和销毁

1.bean的作用域

<bean id="" class="" scope="作用域"/>

singleton :单例 ,在Spring IoC容器中仅存在一个Bean实例 (默认的scope)

单例方式进行bean对象的实例化ClassPathXmlApplicationContext加载时对象就被实例化了(每用一次实例化一个对象)、调用getBean()时将不再创建对象

prototype: 多例 ,每次从容器中调用Bean时,都返回一个新的实例.

ClassPathXmlApplicationContext加载时对象不会被实例化、每次调用getBean()时才进行对象的实例化
总是会延迟初始化lazy-init无论为何值。

request: 用于web开发,将Bean放入request范围 ,request.setAttribute(“xxx”) , 在同一个request 得同一个Bean

session: 用于web开发,将Bean 放入Session范围,在同一个Session 获得同一个Bean

总结:
在开发中主要使用 scope=”singleton”、 scope=”prototype”.对于MVC中的Action使用prototype类型,其他使用singleton

2.bean的初始化和销毁

比如DataSource,SessionFactory最终都需要关闭资源:在Bean销毁之前,都要调用close方法.

<bean id="someBean" class="......" init-method="该类中初始化方法名" destroy-method="该类中销毁方法名">
</bean>

init-method:bean生命周期初始化方法,对象创建后就进行调用

destroy-method:容器被销毁的时候,如果bean被容器管理,会调用该方法。

注意:

如果bean的scope=”prototype”,那么容器只负责创建和初始化,它并不会被spring容器管理销毁。

不使用Spring测试:Spring容器非正常关闭:

这里写图片描述没有调用destroy方法。

解决一:

在applicationContext中有一个子类AbstractApplicationContext、提供了close()方法,而在applicationContext中是不存在的。

@Test         
public void test1(){
    AbstractApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    System.out.println("--------------");
    HelloWorld hello1 = ac.getBean("helloWorld",HelloWorld.class);
    System.out.println(hello1);
    ac.close();
}

这里写图片描述

解决二:

更好的方式:把当前Spring线程作为JVM线程的子线程。也就是说Spring没有运行玩JVM就不会终止。

@Test         
public void test1(){
    AbstractApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    System.out.println("--------------");
    HelloWorld hello1 = ac.getBean("helloWorld",HelloWorld.class);
    System.out.println(hello1);
    ac.registerShutdownHook();
}

这里写图片描述

五、Spring创建对象

1.对象的创建方式

1.构造器实例化

2.静态工厂方式

3.实例工厂方式

4.实现FactoryBean接口实例化:实例工厂变种:集成其他框架使用

2.构造器方式创建

VO类
public class SomeBean {
    public SomeBean(){
        System.out.println("SomeBean 被初始化 ....");
    }
}
---------------------------------------------------------
beans.xml
<bean id="someBean" class="cn.bdqn.vo.SomeBean" />
---------------------------------------------------------
测试类
public class Tester {
    @Test
    public void testSpring1() throws Exception {
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        SomeBean bean = ac.getBean("someBean",SomeBean.class);
        System.out.println(bean);
    }

}

注意:构造函数的访问权限可以是private私有的。

3.静态工厂方式

VO类
public class SomeBean {
    public SomeBean(){
        System.out.println("SomeBean 被初始化 ....");
    }
}
beans.xml
<bean id="someBean" class="cn.bdqn.vo.SomeBeanFactory" factory-method="createSomeBean"/>
工厂类
public static SomeBean createSomeBean(){
    return new SomeBean();
}
测试类
@Test
public void testSpring1() throws Exception {
    ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    SomeBean bean = ac.getBean("someBean",SomeBean.class);
    System.out.println(bean);

}

3.实例工厂方式

对于工厂类只需要把static去掉。

<bean id="factory" class="cn.bdqn.vo.SomeBeanFactory"/>
<bean id="someBean" factory-bean="factory" factory-method="createSomeBean"/>

4.实现FactoryBean接口实例化

对于实例工厂方式变化的只有配置和工厂类

public class SomeBeanFactoryBean implements FactoryBean<SomeBean> {
    //返回SomeBean对象
    @Override
    public SomeBean getObject() throws Exception {
        return new SomeBean();
    }
    //返回SomeBean的类型
    @Override
    public Class<?> getObjectType() {
        return SomeBean.class;
    }
    //是否是单例的
    @Override
    public boolean isSingleton() {
        return true;
    }
}

配置更简化
<bean id="someBean" class="cn.bdqn.vo.SomeBeanFactoryBean" />

4.Bean的生命周期

这里写图片描述

六、Spring的基本配置

1.bean标签

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

    <!-- 
        id      :用于设置bean对象的唯一表示
        name    :用于配置bean对象的别名。同一个bean对象可以有多个别名
                  别名支持使用","、空格,"."等多种符号进行分隔。但是不支持
                  中文符号、!等。
        class   :用于设置Beans的类型(类型 = 包名 + 类名)     
    -->
    <!--  <bean name="user.u1,u2" class="cn.bdqn.vo.User"> -->
    <bean id="user" class="cn.bdqn.vo.User">
        <!-- 
            配置对象的依赖属性
            name    :用于指定依赖属性的名称。设置的值为set方法的名称
            value   :用于设置对象的属性的值
        -->
        <property name="account" value="Mike"></property>
    </bean>
</beans>

2.alias标签

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

    <bean id="user" class="cn.bdqn.vo.User">
        <property name="account" value="Mike"></property>
    </bean>
    <alias name="user" alias="u1"></alias>  
</beans>

3.import标签

<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配置文件
        resource    :设置引入的资源文件
        如果资源文件在指定的包中进行定义的则包的各级之间
        需要使用"/"进行分隔("/"表示路径)
        使用import标签可以更好的实现团队协作及多人开发
   -->
   <import resource="config/spring/users.xml"/>
</beans>

七、依赖注入(DI)

1.概述

依赖注入——Dependency Injection。简称为DI。依赖注入只不过是控制反转(IOC)的另一种说法而已。同一个事物只是站在不同的角度上看。

依赖:bean对象的创建依赖于容器,bean的执行依赖于资源
注入:通过容器为对象设置或装配资源

2.如何注入值

方式一:属性注入,通过setter方法
方式二:构造器注入,通过构造器

3.注入的方式

手动装配

基于xml
基于注解

自动装配:不安全,不推荐。

4.注入哪些类型的值

1.setter方式

1.简单类型:基本类型+String+URL等

private String name;
    private int age;
    private double salary;
    private URL url;

    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
    public void setUrl(URL url) {
        this.url = url;
    }
<bean id="employee" class="cn.bdqn.vo.Employee">
    <property name="name" value="Mike"></property>
    <property name="age" value="20"></property>
    <property name="salary" value="10000"></property>
    <property name="url" value="http://www.baidu.com"></property>
</bean>
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
Employee e = ac.getBean("employee",Employee.class);
System.out.println(e);

2.复合类型

public class EmployeeDao {
    public void save(){
        System.out.println("Dao save is do ......");
    }
}
public class EmployeeService {
    private EmployeeDao dao;

    public void save(){
        dao.save();
        System.out.println("service save is do....");
    }

    public void setDao(EmployeeDao dao) {
        this.dao = dao;
    }


}
<bean id="employeeDao" class="cn.bdqn.vo.EmployeeDao" />
<bean id="employeeService" class="cn.bdqn.vo.EmployeeService">
    <property name="dao" ref="employeeDao"></property>  
</bean>
@Test
public void testSpring1() throws Exception {
    ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    EmployeeService service = ac.getBean("employeeService",EmployeeService.class);
    service.save();
}

有时候,若想只有一个bean引用另一个bean。

<bean id="employeeService" class="cn.bdqn.vo.EmployeeService">
    <property name="dao">
        <bean class="cn.bdqn.vo.EmployeeDao" />
    </property> 
</bean>

3.集合类型

    private Set<String> set;
    private List<String> list;
    private String[] array;
    private Map<String,String> map;
    private Properties prop;

    public void setSet(Set<String> set) {
        this.set = set;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    public void setArray(String[] array) {
        this.array = array;
    }
    public void setMap(Map<String, String> map) {
        this.map = map;
    }
    public void setProp(Properties prop) {
        this.prop = prop;
    }
    @Override
    public String toString() {
        return "CollectionBean [set=" + set + ", list=" + list + ", array="
                + Arrays.toString(array) + ", map=" + map + ", prop=" + prop
                + "]";
    }
<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"> 

    <bean id="collectionBean" class="cn.bdqn.vo.CollectionBean">
        <property name="set">
            <set>
                <value>set1</value>
                <value>set2</value>
                <value>set3</value>
            </set>
        </property>

        <property name="list">
            <list>
                <value>list1</value>
                <value>list2</value>
                <value>list3</value>
            </list>
        </property>

        <property name="array">
            <array>
                <value>array1</value>
                <value>array2</value>
                <value>array3</value>
            </array>
        </property>

        <property name="map">
            <map>
                <entry key="key1" value="value1"  />
                <entry key="key2" value="value2" />
                <entry key="key3" value="value3" />
            </map>
        </property>

        <property name="prop">
            <props>
                <prop key="prop1">value1</prop>
                <prop key="prop2">value2</prop>
                <prop key="prop3">value3</prop>
            </props>
        </property>
    </bean>
</beans>

以上都是通过setter方式对各种类型的注入

2.构造器方式

简单类型

public class Employee {
    private String name;
    private int age;
    private double salary;
    private URL url;

    public Employee(String name, int age, double salary, URL url) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.url = url;
    }
    @Override
    public String toString() {
        return "Employee [name=" + name + ", age=" + age + ", salary=" + salary
                + ", url=" + url + "]";
    }

}
<bean id="employee" class="cn.bdqn.vo.Employee">
    <constructor-arg name="name" value="Rose"></constructor-arg>
    <constructor-arg name="age" value="20"></constructor-arg>
    <constructor-arg name="salary" value="20000"></constructor-arg>
    <constructor-arg name="url" value="http://www.baidu.com"></constructor-arg>
</bean>  

对于<constructor-arg index="" name="" ref="" type="" value="" />的参数

index : 表示第几个参数
type : 参数的类型
name : 参数的名称
value : 参数的简单类型值
ref : 参数的复合类型值

复合类型

public class EmployeeService {
    private EmployeeDao dao;

    public void save(){
        dao.save();
        System.out.println("service save is do....");
    }

    public EmployeeService(EmployeeDao dao) {
        this.dao = dao;
    }

}
 <bean id="employeeDao" class="cn.bdqn.vo.EmployeeDao"></bean>
 <bean id="employeeService" class="cn.bdqn.vo.EmployeeService">
    <constructor-arg name="dao" ref="employeeDao" />
 </bean>

对于集合类型构造器的注入只需要把property标签改成<constructor-arg />其次还要添加构造器。

七、Bean的继承

abstract public class baseDao {
    private String con;

    public void update(String sql,Object...params){
        System.out.println(con);
        System.out.println("sql :"+sql);
    }
    public void setCon(String con) {
        this.con = con;
    }
}
public class EmployeeDao extends baseDao {
    public void save(){
        super.update("INSERT INTO employee.....");
    }
}
<bean id="baseDao" class="cn.bdqn.beanextends.baseDao">
        <property name="con" value="数据库连接中。。。。" />
</bean>

<bean id="employeeDao" class="cn.bdqn.beanextends.EmployeeDao">
</bean>

以上我们会发现会报错,那是当然的,因为我们的baseDao是抽象类是无法实例化的,配置了bean是肯定会出错的,但是我们去掉abstract运行发现并没有向con中注入到值。

Spring的继承: 是对象之间的继承,bean标签之间的继承

解决:

    <bean id="baseDao" abstract="true">
        <property name="con" value="数据库连接中。。。。"></property>
    </bean>

    <bean id="employeeDao" class="cn.bdqn.beanextends.EmployeeDao" parent="baseDao">
    </bean>

既然设置了abstract=true在定义class是没有任何意义的,因为已经制定是抽象的,是不能够实例化的了。

当然,我们还可以特定了类中修改注入的值

<bean id="baseDao" abstract="true">
        <property name="con" value="数据库连接中。。。。"></property>
    </bean>

    <bean id="employeeDao" class="cn.bdqn.beanextends.EmployeeDao" parent="baseDao">
        <property name="con" value="数据库连接中!!!!!!!"></property>
    </bean>

应用:

当多个<bean/>有共同的属性配置,那么可以把共同的属性配置放到父<bean>中去( 设置成abstract的)

八、String的测试

依赖:spring-test-4.3.3.RELEASE.jar

在4.3.3版本中需要Junit4.12或者更高的版本

@RunWith(SpringJUnit4ClassRunner.class):表示先启动Spring容器,把junit运行在Spring容器中

@ContextConfiguration(“”):表示从哪里加载资源文件

若:把@ContextConfiguration(“classpath:applicationContext.xml”) 写成@ContextConfiguration
默认去找的当前测试类名-context.xml配置文件,如:HelloWorldTest-context.xml

测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class Tester {

    @Autowired  //表示自动装配
    private ApplicationContext ac;
    @Test
    public void test(){
        SomeBean bean = ac.getBean("someBean",SomeBean.class);
        System.out.println(bean);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值