Sping框架

Sping在解决什么问题

  • 程序自检的耦合(依赖)--必须依赖mysql的jar包
DriverManager.registerDriver(new com.mysql.jdbc.Driver);
  • 三层架构中的解耦过程--对象的创建方式

     1.强依赖关系 --通过new生成对象

UserDao userDao = new UserDaoImpl();

 

    2. 使用反射获取对象

Object object = Class.forName(properties.get(beanName).toString()).newInstance();

   3.声明beanFactory获取对象

    public static Object getBean(String beanName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Object object = Class.forName(properties.get(beanName).toString()).newInstance();
        return object;
    }
  • BeanFactory工具类和bean.properties配置文件  

    1.bean.properties配置文件--键值对形式,后面是类的路径

userDaoImpl=com.bj169.dao.impl.UserDaoImpl
userServiceImpl=com.bj169.service.impl.UserServiceImpl

   2.BeanFactory工具类,读取Properties类读取配置文件

package com.bj169.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class BeanFactory {
    private static Properties properties = null;

    static {
        //必须初始化properties
        properties = new Properties();
        //通过当前类获取配置文件的输入流InputStream
        InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
        try {
            //加载输入流
            properties.load(resourceAsStream);
        } catch (ExceptionInInitializerError e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Object getBean(String beanName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //通过get方法获取指定beanName的类路径,在通过反射获取对象
        Object object = Class.forName(properties.get(beanName).toString()).newInstance();
        return object;
    }
}
    @Test
    public void test2() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        //获取配置文件中key为userServiceImpl的类对象
        UserService userService = (UserService) BeanFactory.getBean("userServiceImpl");
        userService.addUser();
    }
  • 使用ResourceBundle优化BeanFactory,用Map容器保存key与对象的映射信息 --控制反转IOC底层实现的原理 
package com.bj169.util;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * @ClassName BeanFactory1
 * @Description TODO
 * @Author Administrator
 * @Date 2018/12/11 0011 11:43
 * @Version 1.0
 **/
public class BeanFactory1 {
    //直接读取名字为bean.properties的配置文件,底层封装
    private static ResourceBundle resourceBundle = ResourceBundle.getBundle("bean");
    //存放配置文件里的key和对象的映射关系
    private static Map<String, Object> beanMap = new HashMap<String, Object>();

    static {
        //获取配置文件的所有key
        Enumeration<String> keys = resourceBundle.getKeys();
        while (keys.hasMoreElements()) {
            String beanName = keys.nextElement();
            try {
                //得到beanName对应的object对象  把beanName和对应的对象一起存放在map中
                Object object = Class.forName(resourceBundle.getString(beanName)).newInstance();
                beanMap.put(beanName, object);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    public static Object getBean(String beanName) {
        //通过beanName获取相应的对象
        Object object = beanMap.get(beanName);
        return object;
    }
}

   至此,直接依赖(编译期)关系转为了间接依赖(运行期)

   创建对象的权利(控制权)交出,降低依赖关系(解耦)

   本质上只做一件事儿:解决层次之间的依赖关系

Spring在做什么??

 

轻量级Spring 是非侵入性的 - 基于 Spring 开发的应用中的对象可以不依赖于 Spring API

依赖注入(DI --- dependency injectionIOC)

面向切面编程(AOP --- aspect oriented programming)

容器: Spring 是一个容器, 因为它包含并且管理应用对象的生命周期

框架: Spring 实现了使用简单的组件配置组合成一个复杂的应用. Spring 中可以使用 XML Java 注解组合这些对象

一站式:在 IOC AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库 (实际上 Spring 自身也提供了展现层的 SpringMVC 和 持久层的 Spring JDBC

  • 建立第一个Spring项目,通过idea搭建,选择自动导包和添加配置文件spring-config.xml,不需要进行写BeanFactory,以及封装好两种IOC容器,ApplicationContext(主要)和BeanFactory,下面举例说明。

spring-config.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">
    <bean id="user" class="com.bj169.entity.User" scope="prototype">
        <property name="name" value="杜沛"></property>
        <property name="age" value="23"></property>
    </bean>
    <bean id="userFactory" factory-method="getUser" class="com.bj169.factory.UserFactory"></bean>
</beans>
package com.bj169.test;


import com.bj169.entity.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;


/**
 * @ClassName TestDemo
 * @Description TODO
 * @Author Administrator
 * @Date 2018/12/11 0011 9:34
 * @Version 1.0
 **/
public class TestDemo {
    //IOC的两种容器,ApplicationContext和BeanFactory
    ApplicationContext context = null;
    BeanFactory beanFactory = null;

    @Before
    public void before() {
        //读取配置文件
        context = new ClassPathXmlApplicationContext("spring-config.xml");
    }

    @Before
    public void before1() {
        //读取配置文件
        beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
    }

    @Test
    public void test1() {
        //获取bean对象,立刻加载
        User user1 = (User) context.getBean("user");
        System.out.println(user1);
    }

    @Test
    public void test2() {
        //BeanFactory获得的对象为延迟加载
        User user = (User) beanFactory.getBean("user");
        System.out.println(user);
    }

}
  • 配置文件spring-config的注意事项

配置 bean

配置形式:基于 XML 文件的方式;基于注解的方式

Bean 的三种实例化方式:通过全类名(反射主要)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean

IOC 容器:  BeanFactory & ApplicationContext(主要) 概述

依赖注入的方式:属性注入;构造器注入

注入属性值细节

自动转配

bean 之间的关系:继承;依赖

bean 的作用域:singleton(单例)prototype(多实例);默认的是单例,在bean中通过scope属性设置,WEB 环境作用域

使用外部属性文件

spEL

IOC 容器中 Bean 的生命周期

Spring 4.x 新特性:泛型依赖注入

  • IOC和DI概念

IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式

DI(Dependency Injection) IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接

  •  Spring 中的三种依赖注入方式:属性注入,构造器注入,工厂方法注入(少用)  ----DI
<?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">
    <bean id="user" class="com.bj169.entity.User" scope="prototype">
        <!--构造方法给对象赋值,构造器注入-->
        <!--<constructor-arg value="陈苗" name="name"></constructor-arg>-->
        <!--<constructor-arg value="20" name="age"></constructor-arg>-->
        <property name="name" value="杜沛"></property>
        <property name="age" value="17"></property>
        <!--属性注入-->
        <property name="list">
            <list>
                <value>手机</value>
            </list>
        </property>
        <property name="strings">
            <list>
                <value>1000元</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="1" value="学生"></entry>
            </map>
        </property>
        <!--ref引用其它Bean-->
        <property name="date" ref="date1">
        </property>
    </bean>
    <!--date是一个对象,需要声明Bean-->
    <bean name="date1" class="java.util.Date">
    </bean>
</beans>
  • 使用 utility scheme 定义集合  --声明list Bean,在配置文件里面要添加 util schema 定义 
<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <bean id="newuser" class="com.bj169.entity.newUser">
        <property name="name" value="杜沛"></property>
        <!--newUser类里有一个list<Article>属性,通过声明一个list<Article> Bean来引入属性值-->
        <property name="list" ref="list"></property>
    </bean>
    <bean id="art" class="com.bj169.entity.Article">
        <property name="name" value="厚黑学"></property>
        <property name="price" value="100"></property>
    </bean>
    <bean id="art1" class="com.bj169.entity.Article">
        <property name="name" value="三国演义"></property>
        <property name="price" value="10"></property>
    </bean>
    <!--声明list的Bean,所有外部Bean可以通过id引入这个list Bean-->
    <util:list id="list">
        <!--list Bean里引入其他bean-->
        <ref bean="art"></ref>
        <ref bean="art1"></ref>
    </util:list>
</beans>
  •  使用 p 命名空间,同样要在配置文件里面添加p命名空间的定义
 <bean id="art" class="com.bj169.entity.Article" p:name="杜沛">
        <!--上面通过p给name属性赋值的效果和下面properties的效果一样-->
        <!--<property name="name" value="厚黑学"></property>-->
        <property name="price" value="100"></property>
    </bean>
  • 关于注解

组件扫描(component scanning):  Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件.

特定组件包括:

@Component: 基本注解, 标识了一个受 Spring 管理的组件(Pojo)  --用在一些实体类上

@Repository: 标识持久层组件 (DAO: UserDao <-> UserRepository)

@Service: 标识服务层(业务层)组件注入DAO: UserService(UserServiceImpl)

@Controller: 标识控制层(Action):  注入Service  UserController

对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称

注意:

当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件中声明  <context:component-scan>

base-package 属性指定一个需要扫描的基类包Spring 容器将会扫描这个基类包里及其子包中的所有类.

当需要扫描多个包时, 可以使用逗号分隔.

如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类,

 

<?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">
    <context:component-scan base-package="com.bj169"></context:component-scan>
  •  @Autowired 自动装配 Bean

-@Autowired 注解自动装配具有兼容类型的单个 Bean属性

构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解

默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false

默认情况下, IOC 容器里存在多个类型兼容的 Bean , 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称

@Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.

@Authwired 注解也可以应用在集合属性, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.

@Authwired 注解用java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值

 

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    @Qualifier("userDaoImpl")
    private UserDao userDao ;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void addUser(myUser myUser) {
        userDao.add(myUser);
    }
}
@Repository
public class UserDaoImpl implements UserDao {
    private Session session = null;

    public void setSession(Session session) {
        this.session = session;
    }

    @Override
    public void add(myUser myUser) {
        System.out.println("session" + session);
        System.out.println(session.toString());
        session.save(myUser);
        System.out.println("chenggong");
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值