手记

Spring框架了解、使用(未完成)

Spring初步了解
IOC和DI

IOC(控制反转):获得依赖对象的过程被反转了。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器自动注入。

DI(依赖注入):由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。

Bean容器初始化
  • FileSystemXmlApplicationContext("D:/*/.xml");
  • ClasspathXmlApplicationContext("classpath:*.xml");
  • AnnotationConfigApplicationContext(Application.class);
  • Web应用:
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name></servlet-name>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

Spring注入:在启动Spring容器加载bean配置的时候,完成对变量的赋值行为。

常用的两种注入方式:

  • 设值注入---set
  • 构造注入---construction
先来个小实例

目录结构

applicationContext.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="testService" class="com.imooc.service.impl.TestServiceImpl"></bean>
 </beans>

TestService.java

package com.imooc.service;

public interface TestService {

    void sayHello(String who);

}

TestServiceImpl.java

package com.imooc.service.impl;

import com.imooc.service.TestService;

public class TestServiceImpl implements TestService {

    @Override
    public void sayHello(String who) {
        System.out.println("Hi,"+who);
    }

}

UnitTestBase.java

package com.imooc.test;

import org.junit.After;
import org.junit.Before;
import org.springframework.beans.BeansException;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UnitTestBase {

    private String xmlPath;
    private ClassPathXmlApplicationContext context;

    public UnitTestBase(){
        System.out.println("UnitTestBase无参构造");
    }

    public UnitTestBase(String xmlPath){
        System.out.println("UnitTestBase参构造");
        this.xmlPath = xmlPath;
    }

    @Before
    public void before(){
        System.out.println("before");
        this.context = new ClassPathXmlApplicationContext(this.xmlPath);
    }

    @After
    public void after(){
        System.out.println("after");
        context.destroy();
    }

    @SuppressWarnings("unchecked")
    protected <T extends Object> T getBean(String beanId) {
        try {
            return (T)context.getBean(beanId);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }

    protected <T extends Object> T getBean(Class<T> clazz) {
        try {
            return context.getBean(clazz);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }
}

Test.java

package com.imooc.test;

import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;

import com.imooc.service.TestService;

@RunWith(BlockJUnit4ClassRunner.class)
public class Test extends UnitTestBase {
    public Test(){
        super("classpath*:applicationContext.xml");
        System.out.println("Test构造方法!");
    }

    @org.junit.Test
    public void testBean(){
        TestService t = super.getBean("testService");
        t.sayHello("Tom");
    }

}
Bean

被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的。

<?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" >
    <!--
        id/name:这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。
        class:这个属性是强制性的,并且指定用来创建 bean 的 bean 类。
        scope:这个属性指定由特定的 bean 定义创建的对象的作用域,默认为singleton。
        lazy-init:延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。
    -->
    <bean id="testService" class="com.imooc.service.impl.TestServiceImpl"></bean>
 </beans>
集合注入
<bean id="javaCollection" class="com.imooc.JavaCollection">

      <!-- results in a setAddressList(java.util.List) call -->
      <property name="addressList">
         <list>
            <value>INDIA</value>
            <value>Pakistan</value>
            <value>USA</value>
            <value>USA</value>
         </list>
      </property>

      <!-- results in a setAddressSet(java.util.Set) call -->
      <property name="addressSet">
         <set>
            <value>INDIA</value>
            <value>Pakistan</value>
            <value>USA</value>
            <value>USA</value>
        </set>
      </property>

      <!-- results in a setAddressMap(java.util.Map) call -->
      <property name="addressMap">
         <map>
            <entry key="1" value="INDIA"/>
            <entry key="2" value="Pakistan"/>
            <entry key="3" value="USA"/>
            <entry key="4" value="USA"/>
         </map>
      </property>

      <!-- results in a setAddressProp(java.util.Properties) call -->
      <property name="addressProp">
         <props>
            <prop key="one">INDIA</prop>
            <prop key="two">Pakistan</prop>
            <prop key="three">USA</prop>
            <prop key="four">USA</prop>
         </props>
      </property>

   </bean>
Spring的注解

从Spring3.0开始,Spring JavaConfig项目提供了很多特性,包括使用java而不是xml定义的bean,如:

  • @Configuration
  • @Bean
  • @Import
  • @DependsOn
  • @Component,通用注解,可用于任一个bean
  • @Repository,通常用于DAO类,持久层
  • @Service,通常用于Service类,服务层
  • @Controller,通常用于Controller类,控制层
<context:annotation-config>和<context:component-scan>

<context:annotation-config> 是用于激活那些已经在spring容器里注册过的bean面的注解;

<context:component-scan>除了具有<context:annotation-config>的功能之外,还可以在指定的package下扫描以及注册javabean;通常使用了<context:component-scan>,就不再使用<context:annotation-config>。

关于这两个,具体可参考:https://www.cnblogs.com/leiOOlei/p/3713989.html

bean的作用域@Scope

通常情况下自动查找的Spring组件,其scope是singleton(单列模式),Spring2.5提供了一个标识scope的注解@Scope。

@Scope("prototype")
@Repository
public class TestServiceImpl implements TestService{

...
}

@Autowired
可以将@Autowired理解为传统的setter方法,可用于构造器或成员变量上。

public class TestServiceImpl implements TestService {
    //@Autowired    成员变量上
    private TestDAO testDAO;

    public TestServiceImpl(){
        System.out.println("TestServiceImpl is created a instance.");
    }
    @Autowired  //构造器上
    public TestServiceImpl(TestDAO testDAO){
        this.testDAO = testDAO;
    }

    //@Autowired    setter方法上
    public void setTestDAO(TestDAO testDAO) {
        System.out.println("testDAO is injected.");
        this.testDAO = testDAO;
    }

    @Override
    public void sayHello(String who) {
        System.out.println("Hi,"+who);
    }

}

@Autowired 的(required=false)选项

默认情况下,@Autowired 注释意味着依赖是必须的,它类似于 @Required 注释,然而,你可以使用 @Autowired 的 (required=false) 选项关闭默认行为。

面向切面编程AOP

通过预编译方式和运行期动态代理,实现程序功能的统一维护的一种技术。

主要功能是:日志记录、性能统计、安全控制、事务处理、异常处理。

AOP相关点介绍
  • 切面Aspect:一个关注点的模块化,这个关注点可能会横切多个对象;
  • 连接点Joinpoint:程序执行过程中的某个特定的点;
  • 通知Advice:在切面某个特定的连接点上执行的动作;
  • 切入点Pointcut:匹配连接点的断言,在AOP中通知和一个切入点表达式关联;
  • 引入Introduction:在不修改类代码的前提下,为类添加新的方法和属性;
  • 目标对象Target Object:被一个或多个切面通知的对象;
  • AOP代理AOP Proxy:AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能);
  • 织入Weaving:把切面连接到其他的应用程序或者对象上,并创建一个被通知的对象,分为编译时织入、类加载时织入、执行时织入。
Advice类型
  • 前置通知Before advice:在某个连接点之前执行的通知,但不能阻止连接点前的执行(除非抛出一个异常);
  • 返回后通知After returning advice:在某个连接点正常完成后执行的通知;
  • 抛出异常后通知After throwing advice:当方法抛出异常退出时执行的通知;
  • 后通知After(finally)advice:当某个连接点退出的时候执行的通知,不论是正常返回还是异常返回;
  • 环绕通知Around advice:包围一个连接点的通知,通知方法的第一个参数必须是ProceedingJoinPoint类型。
pointcut
  • execution(public * *(..)) 执行所有public方法时
  • execution(* set*(..)) 执行所有set开始的方法时
  • execution(* com.imooc.service.TestService.*(..)) 执行TestService类中所有的方法时
  • execution(* com.imooc..(..)) 执行com.imooc包下所有的方法
  • execution(* com.imooc...(..)) 执行com.imooc及其子包下所有的方法
AOP实例(在上一实例的基础上实现)

目录结构


applicationContext.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"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd" >

    <bean id="testService" class="com.imooc.service.impl.TestServiceImpl">
        <property name="testDAO" ref="testDAO"></property>
    </bean>

    <bean id="testDAO" class="com.imooc.dao.TestDAO"></bean>
    <!-- 切面实例-->
    <bean id="testAspect" class="com.imooc.aop.TestAspect"></bean>

    <aop:config>
        <aop:aspect id="testAspectAOP" ref="testAspect">
            <aop:pointcut expression="execution(* com.imooc.service.impl.*Impl.*(..))" id="testBusiness"/>
            <aop:before pointcut-ref="testBusiness" method="before"/>
        </aop:aspect>
    </aop:config>
 </beans>

TestAspect.java

package com.imooc.aop;

public class TestAspect {
    public void before(){
        System.out.println("我是切面~~~");
    }
}

运行结果

UnitTestBase有参构造
Test构造方法!
before
TestServiceImpl is created a instance.
TestDAO is created a instance.
testDAO is injected.
我是切面~~~
Hi,Tom
after
0人推荐
随时随地看视频
慕课网APP