Spring

Spring入门

使用 spring 的 IOC 解决程序耦合

bean.xml配置

ApplicationContext的三个实现类:

ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下
FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有权限)
AnnotationConfigApplicationContext:用于读取注解,创建容器

核心容器的两个接口引发出的问题

ApplicationContext单例对象适用:它在构建核心容器的时候,创建对象是采用立即加载的方式,也就是说,只要一读取完配置文件就创建
BeanFactory多例对象适用:它在构建核心容器的时候,创建对象是采用延迟加载的时候
获取核心容器对象

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");

根据id获取bean对象,两种方式

        IAccountService service = (IAccountService) applicationContext.getBean("accountService");
        IAccountService accountService = applicationContext.getBean("accountService",IAccountService.class);
创建bean的三种方式

第一种方式:使用默认构造函数创建
在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。

<bean id="accountService" class="com.service.impl.AccountServiceImpl"></bean>

第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器

 <bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>

第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)

<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>
bean标签的scope属性:

作用:用于指定bean的作用范围
取值: 常用的就是单例的和多例的
singleton:单例的(默认值)
prototype:多例的
request:作用于web应用的请求范围
session:作用于web应用的会话范围
global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="prototype"></bean>
bean对象的生命周期

单例对象
出生:当容器创建时对象出生
活着:只要容器还在,对象一直活着
死亡:容器销毁,对象消亡
总结:单例对象的生命周期和容器相同
多例对象
出生:当我们使用对象时spring框架为我们创建
活着:对象只要是在使用过程中就一直活着。
死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收

spring中的依赖注入

构造函数注入:
标签中的属性
type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
name:用于指定给构造函数中指定名称的参数赋值 常用的
=============以上三个用于指定给构造函数中哪个参数赋值===============================
value:用于提供基本类型和String类型的数据
ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象

    <bean id="accountService" class="com.service.impl.AccountServiceImpl">
        <constructor-arg name="name" value="jack"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg name="birthday" ref="now"></constructor-arg>
    </bean>
    <!-- 配置一个日期对象 -->
    <bean id="now" class="java.util.Date"></bean>
public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

set方法注入 常用的
涉及的标签:property
出现的位置:bean标签的内部
标签属性:
name:用于指定给构造函数中指定名称的参数赋值
=============以上三个用于指定给构造函数中哪个参数赋值===============================
value:用于提供基本类型和String类型的数据
ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象

<bean id="accountService2" class="com.service.impl.AccountServiceImpl2">
        <property name="name" value="tom"></property>
        <property name="age" value="21"></property>
        <property name="birthday" ref="data"></property>
    </bean>

    <bean id="data" class="java.util.Date"></bean>

复杂类型的注入/集合类型的注入
用于给list结构集合注入的标签:
list array set
用于给map结构集合注入的标签:
map props

private String name;
    private Integer age;
    private Date birthday;

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

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
<bean id="accountService3" class="com.service.impl.AccountServiceImpl3">
        <property name="myStr">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>
        <property name="myList">
            <list>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </list>
        </property>
        <property name="mySet">
            <set>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </set>
        </property>
        <property name="myMap">
            <map>
                <entry key="1" value="jack"></entry>
                <entry key="2">
                    <value>tom</value>
                </entry>
            </map>
        </property>
        <property name="myProp">
            <props>
                <prop key="testA"></prop>
                <prop key="testB"></prop>
            </props>
        </property>
    </bean>

bean.xml和注解配置

告知spring在创建容器时扫描的包,配置所需要的标签不是在bean的约束中,而是一个名称为context名称空间和约束中

<context:component-scan base-package="com"></context:component-scan>
用于创建对象的:

@Component:
作用:用于把当前类对象存入spring容器中
属性:value:用于指定bean的id
@Controller:一般用于表现层
@Service:一般用于业务层
@Repository:一般用在持久层

用于注入数据的

@Autowired:
作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功
如果ioc容器中没有任何bean类型和要注入的类型相匹配,则报错
如果ioc容器中有多个类型匹配时:
出现为位置:可以是成员变量上,也可以是方法上
细节:在使用注解注入的时候set就不是必须的了
@Qualifier:
作用:再按照类型注入的基础上再按照名称注入。在给类成员注入的时候不能单独使用,但在给方法参数注入时可以
属性:value:用于注入bean的id

    @Autowired
    @Qualifier("accountDao1")
    private IAccountDao accountDao = null;

Resource
作用:直接按照bean的id注入,他可以独立使用
属性:name:用于之指定bean的id

    @Resource(name = "accountDao1")
    private IAccountDao accountDao = null;

上述基本类型和String都无法注入 集合只能用xml来实现

@Value:
作用:用于注入基本类型和String的数据
属性:
value:用于指定数据的值 它可以使用springEL(spring的el表达式)
spel的写法${表达式};

用于改变作用范围的

bean中的scope属性 一样
@Scope
作用:用于指定bean作用范围
属性:
value:指定范围的取值。常用取值。singleton prototype

和生命周期相关的(了解)

bean中的使用init_method destroy-method 一样
@PreDEstroy
作用:用于指定销毁
@PostConstruct
作用:用于指定初始化

全用注解

该类是一个配置类,它的作用和bean.xml是一样的

Spring中的注解
@Configuration
指定当前类是一个配置类
细节:当配置类作为AnnotationConfigApplicationContext对象的参数时可以不写
@ComponentScan
用于通过注解指定Spring在创建容器时要扫描的包
属性:
value:它和basePackage的作用时一样的,都是用于指定创建容器时要扫描的包
使用此注解就相当于在xml中配置了:<context:component-scan base-package="com</context:component-scan>
@Bean:
用于把当前的方法返回值作为bean对象存入spring的容器中,
注解的属性:
name:用于指定bean的id,默认值是当前方法的名称
细节:
当我们使用注解配置的时候,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象查找的方式和Autowired注解的作用一样
@Import:
用于导入其他配置文件
属性:
value:用于指定其他配置类的字节码文件
当我们使用Import的注解之后,有Import注解的类就是父配置类,而导入的时子配置类
@PropertySource:
用于指定properties文件的位置
属性:value:指定文件的名称和路径
关键字:classpath 表示类路径下

@Configuration
//@ComponentScan(basePackages = "com")
@ComponentScan("com")
//@EnableAspectJAutoProxy   AOP  注解
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {

}
使用junit单元测试

spring整合junit
1,导入spring整合的jar坐标
2,使用junit提供的一个注解把原有的main方法替换了,替换成spring提供的
@Runwith
3,告知spring的运行器,spring和ioc的创建是基于xml还是注解的,并说明其位置
@ContextConfiguration
location:指定xml文件的位置,加上classpath关键字,表示在类路径下
classes:指定注解类
当我们使用spring 5.x时 junit的jar必须是4.12及以上

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)  注解的时候
@ContextConfiguration("classpath:bean.xml") 有配置文件的时候
public class AccountServiceTest {
    @Autowired
    private IAccountService accountService = null;
}
private ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");  xml文件配置
private ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class); 注解配置

spring中xml的AOP的配置步骤

1,把通知的Bean也交个spring来管理

2,使用aop:config标签表明AOP的开始配置

3,使用aop:aspect标签表明配置切面

id属性:是给切面提供一个标识符
ref属性:是指定通知类bean的id

4,在aop:aspect标签的内部使用对应标签来配置通知的类型

我们现在示例是让printLog方法在切入点方法之前,所以是前置通知
aop:before: 表示前通知
method:用于指定Logger类中那个方法是前置的
pointcut:用于指定切入点表达式:该表达式的含义指的是对业务层中哪些方法增强

切入点表达式:

关键字:execution(表达式)
表达式:
访问修饰符 返回值 包名类名方法名参数列表)
public void com.service.impl.AccountServiceImpl.saveAccount(参数)
访问修饰符可以省略
返回值可以使用号,表示任意返回值
包名可以使用
号,表示任意包,但是有几级包,需要写几个*
使用..来表示当前包,及其子包
类名可以使用号,表示任意类
方法名可以使用
号,表示任意方法
参数列表可以使用*,表示参数可以是任意数据类型,但是必须有参数
参数列表可以使用..表示有无参数均可,有参数可以是任意类型
全通配写法

 * *..*.*(..)

实际开发中

* com.service.impl.*.*(..)
<aop:config>
        <!--配置切入点表达式  id指定属性的唯一标识   expression属性用于指定表达式内容
               他在aop:aspect 内部只能当前切面使用
               他还可以写在外面  此时所有切面都就可以用-->
        <aop:pointcut id="pt1" expression="execution(* com.service.impl.*.*(..))"></aop:pointcut>
        <!--配置切面-->
        <aop:aspect id="logAdvice" ref="logger">
            <!--配置通知类型,并且建立通知方法和切入点方法关联-->
            <!--前置通知-->
            <aop:before method="printLog" pointcut-ref="pt1" ></aop:before>
            <!--后置通知   和异常通知只能存在一个   在方法正确的执行之后执行-->
            <aop:after-returning method="after" pointcut-ref="pt1"  ></aop:after-returning>
            <!--异常通知   再方法发生异常的时候执行-->
            <aop:after-throwing method="exception" pointcut-ref="pt1" ></aop:after-throwing>
            <!--最终通知 无论切入点方法是否正常执行  他都会执行的-->
            <aop:after method="last" pointcut-ref="pt1" ></aop:after>
            <!--配置切入点表达式  id指定属性的唯一标识   expression属性用于指定表达式内容
               他在aop:aspect 内部只能当前切面使用
               他还可以写在外面  此时所有切面都就可以用-->

            <aop:pointcut id="pt1" expression="execution(* com.service.impl.*.*(..))"></aop:pointcut>

            <!--环绕通知-->
            <aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around>
        </aop:aspect>
    </aop:config>

注解配置AOP

@Aspect:表示当前面是一个切面
@Pointcut:表达式:关键字:execution(表达式)
@Before():
@AfterReturning():
@AfterThrowing():
@After():

配置开启spring注解AOP的支持 在Bean.xml中
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

spring基于xml的生命事务控制的配置步骤

1,配置事务管理器
2,配置事务通知

导入事务的约束 tx的名称空间和约束,同时也需要aop的
使用tx:advice标签配置事务通知
属性:
id:给事务通知起个唯一标识
transaction-manager:给事务通知提供一个事务管理器引用

3,配置aop中的通用切入点表达式
4,建立事务通知和切入点表达式的对应关系
5,配置事务的属性

事务通知标签的内部txAdvice
isolation:用于指定事务的隔离级别,默认值是DEFAULT, 表示使用数据库的默认隔离级别
propagation:用于指定事务的传播行为,默认值是REQUIRED,表示一定会有事务,增删改的选择 查询方法可以用SUPPORTS
read-only:用于指定事务是否值读,只有查询方法才能设置为true,默认值是false,表示读写
timeout:用于指定事务的超时时间,默认值是-1,表示永不超时,如果指定数值,以秒为单位
no-rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚,没有默认值,表示任何异常都回滚
rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚,没有默认值,表示任何异常都回滚

    <!--aop-->
    <aop:config>
        <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut>
        <!--建立事务通知和切入点表达式的对应关系-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
    </aop:config>
    <!--配置事务管理器-->
    <bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManger">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" read-only="false"></tx:method>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
        </tx:attributes>
    </tx:advice>

spring基于注解的生命事务控制的配置步骤

1,配置事务管理器
2,开启spring对注解事务的支持
3,在需要事务支持的地方使用

@Transactional注解
配置事务管理器

    <bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

开启spring对注解事务的支持

    <tx:annotation-driven transaction-manager="transactionManger"></tx:annotation-driven>

在需要事务支持的地方使用

   @Transactional
   public class AccountServiceImpl implements IAccountService {}
全注解

bean.xml的文件
开启spring对注解事务的支持

@Configuration
@ComponentScan("com.itheima")
@Import({JdbcConfig.class,TransactionConfig.class})
@PropertySource("jdbcConfig.properties")
//开启spring对注解事务的支持
@EnableTransactionManagement
public class SpringConfiguration {
}

配置事务管理器

public class TransactionConfig {
    /**
     * 用于创建事务管理器对象
     * @param dataSource
     * @return
     */
    @Bean(name = "transactionManager")
    public PlatformTransactionManager createTransactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容