乐趣区

关于java:spring

一、Spring 简介
1、什么是 Spring

Spring 是一个用于简化企业级 Java 开发的利用框架
Spring 以 IoC(管制反转)和 AOP(面向切面编程)为外围,提供了体现层的 SpringMVC 反对,也提供了业务层的申明式事务反对,以及提供了长久层的 JdbcTemplate 反对。Spring 除了本身所提供的性能外,还能够作为一个粘合剂,用于整合优良的第三方技术框架。SSH(spring 整合 Struts2、spring 整合 Hibernate)SSH(spring 整合 SpringMVC、spring 整合 Mybatis)

2、Spring 的劣势

1)不便解耦,简化开发
2)提供了 AOP、申明式事务反对(前面阶段解说)3)对 JavaEE 进行了封装,升高开发难度。。。

二、Spring 的 IoC
1、耦合、解耦的概念

耦合: 是指对象和对象之间产生的依赖关系, 依赖关系越高, 耦合性越高, 依赖关系越低, 耦合性越低。在开发我的项目时,尽量不要让对象之间的依赖关系太高。解耦: 升高对象之间耦合性的过程叫做解耦(解耦只是升高耦合性, 但不能彻底消除)
Class AnimalTest{Animal ani = spring 容器对象.getBean("animal")
    //Animal ani = new Cat();}
interface Animal{}
class Cat implements Animal{}
------------------------------------------------
beans.xml
    animal    com.tedu.Cat

2、Spring IoC 概念

IoC(Inverse Of Control):管制反转,是指将对象的创立交给框架负责
    在 spring 框架之前,当须要对象,咱们负责管制对象的创立(new 的模式),以及对象的销毁
    但因为 new 对象会造成对象之间的依赖关系晋升(即耦合度晋升)
    因而能够将对象的创立交给 spring 负责,将创建对象的权力交给框架,这里咱们称之为 "管制反转"
    

3、Spring IoC 入门

1)创立 Maven 的 java 工程:CGB-SPRING-01
2)在 pom.xml 文件中导入 junit、spring 的依赖包
3)提供 com.tedu.pojo.User 类(将 User 类的实例交给 spring 框架创立)
4)在 src/main/resources 下提供 spring 的配置文件 --beans.xml, 并增加如下配置
    <!-- 将 User 作为 bean 拆卸到 spring 容器中(将 User 类的实例交给 spring 容器创立)
        id 属性: 定义一个编号, 未来通过这个编号能够获取以后类的实例(id 必须是惟一的)id 值通常是以后类的类名(但首字母小写), 或者以后类父接口的接口名(首字母小写)
        class 属性: 指定以后类的全类名(spring 框架会通过反射 + 全类名创立该类的实例) -->
    <bean id="user"  class="com.tedu.pojo.User">
    
5)提供测试类,测试 spring 的 IoC
    public class SpringTest {
        // 获取 spring 的容器对象
        ClassPathXmlApplicationContext ac = 
                new ClassPathXmlApplicationContext("beans.xml");
        /* 1、测试 spring 的 IoC */
        @Test
        public void testIoC(){// 从 spring 容器中获取 User 类的实例(对象)
            User user = (User)ac.getBean("user"); // 依据 id 获取 bean
        }
    }
            

三、Spring 的单实例和多实例

/*
 * 单例: 默认 spring 容器中所有的 bean 对象都是单例的(即每个类只创立一个对象)
 *         长处: 无论获取一个 bean 多少次, 返回都是同一个实例(因为只创立了一个实例)
 *             能够节俭内存空间, 缩小资源节约。*         毛病: 可能会引发线程平安问题(如果这个惟一对象上有共享数据, 并且多个线程会同时
 *             操作这个共享数据)*         单例的 bean 是在 beans.xml 文件一被读取就会创立实例, 而且会存到 bean 池中
 *
 * 多例: 如果在 bean 标签上设置 scope="prototype", 以后 bean 对象就是多例的
 *        <bean id="user" scope="prototype" class="com.tedu.pojo.User">
 *         每次获取以后类的实例, spring 容器都会创立该类的新的实例
 *         长处: 不会引发线程平安问题(因为每个线程持有的实例是不同的)
 *         毛病: 因为每次获取都会创立新的实例, 会占用服务器的内存空间, 浪费资源
 *         多例的 bean 是每次获取时才会创立实例, 而且创立的实例不会存到 bean 池中
 * 
 * 总结: 从应用频次上, 如果一个对象应用的频率特地高, 倡议应用单例
 *         反过来说, 如果一个对象应用频率特地低, 倡议应用多例。*/
@Test
public void testScope() {// 获取 UserInfo 类的实例(多例)
    UserInfo info1 = (UserInfo)ac.getBean("userInfo");
    UserInfo info2 = (UserInfo)ac.getBean("userInfo");
    System.out.println(info1 == info2); //false, 地址不相等, 阐明不是同一个对象
    
    // 获取 User 类的实例(单例)
    User u1 = (User)ac.getBean("user");
    User u2 = (User)ac.getBean("user");
    System.out.println(u1 == u2); //true, 因为是同一个对象, 所以地址相等
}

四、Spring 的 DI

/*
 * 测试 spring 的 DI(依赖注入)*     依赖注入:在创建对象的同时或者之后,为对象的属性赋值
 *     1)set 办法注入:在创建对象之后,框架在底层调用对象的 setXxx 办法为 xxx 属性赋值
 *         例如: 调用 setName 办法给 name 属性赋值
 *     2)构造方法注入:底层是在创建对象的同时, 通过构造方法给对象的属性赋值
 */
@Test
public void testDI() {
    // 获取 User 类的实例
    User user = (User)ac.getBean("user");
    System.out.println(user);
}
========================================================
<!-- 应用 set 办法为 User 对象的 name、age、info 变量赋值
    须要留神的是: name 属性指定的值, 在以后类中得有对应的 set 办法 -->
<bean id="user"  class="com.tedu.pojo.User">
    <property name="name"  value="韩少云" />
    <property name="age"  value="30" />
    <property name="info"  ref="userInfo"/>
</bean>
========================================================
<!-- 应用构造方法为 User 对象的 name、age、info 属性赋值
    其中 name 属性的值 要和构造方法上形参的名字保持一致
 -->
<bean id="user"  class="com.tedu.pojo.User">
    <constructor-arg name="name"  value="马云"/>
    <constructor-arg name="age"  value="38"/>
    <constructor-arg name="info"  ref="userInfo"/>
</bean>
========================================================

五、Spring 的全注解开发
1、spring 全注解开发入门

1)创立 Maven 的 java 工程:CGB-SPRING-02
2)在 pom.xml 文件中导入 junit、spring 的依赖包
3)提供 com.tedu.pojo.User 类(将 User 类的实例交给 spring 框架创立)
4)提供 com.tedu.AppConfig 类,作为 Java 配置类
========================================================
/* @Configuration: 告诉 spring 框架这是一个 Java 配置类, spring 框架通过
 * 这个类中的配置, 生成 spring 容器对象。AppConfig 类 == beans.xml 文件
 */
@Configuration
public class AppConfig {/* @Bean(name="user"): 将以后办法的返回值作为 bean 拆卸到 spring 容器中
     *         其中 name 指定的值就是 bean 的 id 值(即 bean 的名称), 相当于 <bean> 标签
     *         如果不增加括号及其中的 name 属性, bean 的 id 值就是办法名 */
    @Bean(name="user")
    public User getUser() {User user = new User();
        user.setName("赵云");
        user.setAge(28);
        return user;
    }
}
========================================================
5)提供测试类,测试 spring 的全注解开发
public class SpringTest {
    // 获取 spring 的容器对象
    AnnotationConfigApplicationContext ac = 
            new AnnotationConfigApplicationContext(AppConfig.class);
    /* 1、测试 spring 的全注解开发 */
    @Test
    public void testIoC01() {
        // 从 spring 容器中获取 User 类的实例
        User u1 = (User)ac.getBean("user");
        System.out.println(u1);
    }
}

2、通过扫描拆卸 Bean

1)将下面 AppConfig 中 @Bean 注解及标记的 getUser 办法 正文或者间接删除
2)在 AppConfig 类上增加 @ComponentScan 注解
    /* @Configuration: 告诉 spring 框架这是一个 Java 配置类, spring 框架通过
     * 这个类中的配置, 生成 spring 容器对象。AppConfig 类 == beans.xml 文件
     * @ComponentScan: 用于配置以何种策略扫描拆卸 bean, 如果前面什么都不加
     *         默认扫描以后类所在的包 (com.tedu) 及其子包(com.tedu.*)
     *         如果扫描到包中的类上有 @Component 注解, 就会将这个类作为 bean 进行拆卸
     */
    @Configuration
    @ComponentScan
    public class AppConfig {/* ... */}
3)在 User 类上增加 @Component("user") 注解
    @Component("user")
    public class User {...}
4)再执行 SpringTest 类中 testIoC01 办法进行测试

@ComponentScan: 配置以何种形式扫描拆卸 bean, 默认扫描以后类所在的包及其子包
    比方, 以后类是 com.tedu.AppConfig, 所在的包就是 com.tedu
    默认扫描的包就是 com.tedu 包以及以 com.tedu 结尾的所有子包
@ComponentScan(basePackages = "com.tedu.dao")
    basePackages 指定扫描哪个包, 下面指定了只扫描 com.tedu.dao 包
@ComponentScan(basePackages = { "com.tedu.dao", "com.tedu.service"} )
    basePackages 同时能够指定扫描多个包, 将多个包放在一个数组中即可, 
    下面指定了扫描 com.tedu.dao 包 和扫描 com.tedu.service 包

3、@AutoWired 主动拆卸(依赖注入)

如果是给一个字符串类型的变量或者数值类型的变量赋值, 能够间接通过 @Value 注解给对象的属性赋值。1)批改 User 类, 在 User 类中增加一个 Animal 类型的 animal 属性, 并提供对应的 get 和 set 办法
2)重写 User 类中的 toString 办法
3)增加一个 com.tedu.pojo.Animal 接口, 并未 Animal 接口提供一个实现类 --com.tedu.pojo.Dog
4)通过 @AutoWired 注解为 User 对象的 animal 属性赋值, 赋的值是一个 Animal 类型的对象

@Component("dog") // 将 Dog 类作为 bean 拆卸到 spring 容器中(spring 容器中是蕴含 Dog 对象的)public class Dog implements Animal

@Autowired
private Animal animal;

@Autowired 注解的作用:1)@AutoWired 注解是咱们应用十分多的注解之一,它能够将定义好的 bean 对象(比方 Dog 对象)作为值 赋值给其它对象的属性。这个过程是主动实现的,咱们称之为主动拆卸(依赖注入)2)@AutoWired 注解默认优先依照(Animal)类型到 spring 容器中进行查找 bean,如果找到一个则间接将这个 bean 对象作为值赋值给 animal 属性。如果找不到,则抛出异样!3)如果该类型(Animal)的 bean 在 spring 容器中有多个,此时还会依据变量名 / 属性名去匹配,如果变量名 / 属性名 和 bean 的 id 值雷同,就能够主动拆卸。如果都不雷同,也会抛出异样。4)如果该类型(Animal)的 bean 在 spring 容器中有多个,能够通过 @Qualifier 显式的为属性指定要注入哪一个名称的 bean

4、@Scope 指定 bean 的作用范畴

@Scope("prototype")
public class User{...}
如果不指定 scope 属性或者 @Scope 注解, 在 spring 容器中所有的 bean 都是单实例的(spring 容器为所有的类只创立一个实例。)
如果指定 scope="prototype" 或者 @Scope("prototype"), 能够指定以后 bean 为多实例, 即每次通过 spring 容器获取以后类的实例, 都会创立新的 bean 对象并返回!
退出移动版