Spring学习笔记

Spring学习笔记

核心: IOC AOP

基本配置文件:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">


</beans>

IOC

ioc 的作用: 解耦

IOC 解决的问题:

依赖注入(DI)是实现 IOC 的一种方法。

  1. 如果一个类A 的功能实现需要借助于类B,那么就称类B是类A的依赖,如果在类A的内部去实例化类B,那么两者之间会出现较高的耦合,一旦类B出现了问题,类A也需要进行改造,如果这样的情况较多,每个类之间都有很多依赖,那么就会出现牵一发而动全身的情况,程序会极难维护,并且很容易出现问题。
  2. 假如现在有N多个类,需要用到Class B,那就需要在类里面实例化N多次,这样对于后期的维护和管理都是不方便的,如果后期需求发生改变,那更改量有大很多。

IOC创建对象的方式

默认使用对象的无参构造方法创建对象, 当对象没有无参构造的时候会出现异常, 此时需要指定使用带参数的构造方法。

默认使用无参构造:

<bean id="user" class="com.xtyuns.pojo.User">
    <property name="name" value="Spring"/>
</bean>

使用有参构造(使用name方法):

<bean id="user" class="com.xtyuns.pojo.User">
    <constructor-arg name="name" value="Spring"/>
</bean>

有参构造还有两种不常用的方法: index(参数索引), type(参数类型)

总结
  1. 在配置加载的时候, 容器管理的对象就已经初始化加载了。

配置

  1. bean 标签

    <bean id="user" class="com.xtyuns.pojo.User" name="u">
        <constructor-arg name="name" value="Spring"/>
    </bean>
    
    <!--
        id: 对象名
        class: 类的全限定名
        name: 对象的别名, 相当于 alias 标签, 但是更强大: 可以设置多个别名
    -->
    
  2. import 标签

    <import resource="beans2.xml"/>
    
    <!-- 作用: 引入其他的 bean.xml 文件, 可以将所有的bean汇总到同一个xml中 -->
    

Bean的注入方法

package com.xtyuns.pojo;

public class User {
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

package com.xtyuns.pojo;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class Student {
    String name;
    User teacher;
    String[] games;
    List<String> books;
    Set<String> hobbys;
    Map<String, String> card;
    Properties info;

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public User getTeacher() {
        return teacher;
    }

    public void setTeacher(User teacher) {
        this.teacher = teacher;
    }

    public String[] getGames() {
        return games;
    }

    public void setGames(String[] games) {
        this.games = games;
    }

    public List<String> getBooks() {
        return books;
    }

    public void setBooks(List<String> books) {
        this.books = books;
    }

    public Set<String> getHobbys() {
        return hobbys;
    }

    public void setHobbys(Set<String> hobbys) {
        this.hobbys = hobbys;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }
}

基于构造函数的依赖注入

默认构造
<bean id="u1" class="com.xtyuns.pojo.User">
    <property name="name" value="Spring"/>
</bean>
带参构造
<bean id="stu" class="com.xtyuns.pojo.Student">
    <constructor-arg name="name" value="xtyuns"/>
</bean>

基于setter方法的依赖注入

对象引用
<bean id="stu" class="com.xtyuns.pojo.Student">
    <property name="teacher" ref="u1"/>
</bean>
数组注入
<bean id="stu" class="com.xtyuns.pojo.Student">
    <property name="games">
        <array>
            <value>英雄联盟</value>
            <value>王者荣耀</value>
            <value>守望先锋</value>
            <value>刺激战场</value>
        </array>
    </property>
</bean>
List 注入
<bean id="stu" class="com.xtyuns.pojo.Student">
    <property name="books">
        <list>
            <value>红楼梦</value>
            <value>西游记</value>
            <value>水浒传</value>
            <value>三国演义</value>
        </list>
    </property>
</bean>
Map 注入
<bean id="stu" class="com.xtyuns.pojo.Student">
    <property name="card">
        <map>
            <entry key="编号" value="18001"/>
        </map>
    </property>
</bean>
Set 注入
<bean id="stu" class="com.xtyuns.pojo.Student">
    <property name="hobbys">
        <set>
            <value>吃饭</value>
            <value>睡觉</value>
            <value>看电影</value>
        </set>
    </property>
</bean>
Properties 注入
<bean id="stu" class="com.xtyuns.pojo.Student">
    <property name="info">
        <props>
            <prop key="学号">18001</prop>
        </props>
    </property>
</bean>

其他注入

p命名空间
xmlns:p="http://www.springframework.org/schema/p"
c命名空间
xmlns:c="http://www.springframework.org/schema/c"

自动装配

<bean autowire="byName" id="people" class=""
<!-- 会自动在Spring上下文中查找setxxx() 方法所对应的beanid, 并进行自动装配 -->

<bean autowire="byType" id="people" class=""
<!-- 会自动在Spring上下文中查找setxxx() 方法所对应Bean的类型, 并进行自动装配 -->

byName 依赖 id 进行注入

byType 依赖 class 进行注入

常用的是使用注解进行自定装配Bean, 详见: 注解开发

注解开发

Spring4 之后使用注解开发需要导入 Spring-aop的jar包, 并导入 context约束

  1. 首先指定注解扫描包的路径

    <context:component-scan base-package="com.xtyuns"/>
    
    <!-- 当使用 <context:component-scan/> 后, 就可以将 <context:annotation-config/> 省略了 -->
    
  2. 在相应的Bean上使用注解即可

Spring JavaConfig

@Configuration
定义配置类, 替换xml配置文件

@ComponentScan("com.xtyuns")
定义注解扫描包路径

@Import(Config.class)
引入另一个配置类

@ImportResource("")
引入xml配置类

@Bean("name")
定义一个Bean, 相当于<Bean id="name"...(使用注解定义的Bean开启扫描即可, 无须再次定义Bean)

定义Bean的注解

@Conponent
@Conponent("Bean的名称")
定义Bean, 不好归类时使用

@Repository   
@Repository("Bean的名称")
定义DAO层Bean

@Service          
@Service("Bean的名称")
定义业务层Bean

@Controller
@Controller("Bean的名称")
定义控制层Bean 

自动装配Bean

@Autowired
@Autowired(required=false)
忽略当前要注入的Bean, 如果有直接注入, 没有则跳过, 不会报错

@Qualifier
按名称装配Bean, 与@Autowired组合使用, 解决按类型匹配找到多个Bean问题

@Resource(name="xxx", type="xxx")
默认按名称装配, 当找不到名称匹配的Bean再按类型装配, 也可以通过参数显式指定装配方式

Autowired 默认使用 byType的方式进行注入, 当存在多个相同Type的时候, 会使用变量名进行byName注入, 或者使用@Qualifier注解来通过byName的方式指明使用哪一个实现类

定义Bean的作用域和生命过程

@Scope("prototype")
值有:singleton, prototype, session, request, session, globalSession

@PostConstruct 
相当于init-method, 使用在方法上, 当Bean初始化时执行

@PreDestroy 
相当于destory-method, 使用在方法上, 当Bean销毁时执行

声明式事务

@Transactional 

AOP

AOP 的底层是代理模式

需要导包: aspectjweaver

AOP的名词结束

  1. Advice (通知/增强)

    要增强的代码/功能, 如日志功能

  2. Joinpoint (连接点)

    spring允许使用通知的地方 (@Before, @After, @AfterRunning, @AfterThrowing, @Around)

  3. Pointcut (切入点)

    进行注入Advice 的位置, 而连接点是允许注入的位置

  4. Aspect (切面)

    切入点+通知 = 切面

  5. Target (目标对象)

    被代理对象

  6. Weaving (织入)

    将通知应用到连接点的过程

  7. Proxy (代理)

    生成的代理对象

AOP Demo

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

    <bean id="user" class="com.xtyuns.service.UserServiceImpl"/>
    <bean id="beforeLog" class="com.xtyuns.log.BeforeLog"/>
    <bean id="timeLog" class="com.xtyuns.log.TimeLog"/>

    <aop:config>
        <aop:pointcut id="cutp" expression="execution(* com.xtyuns.service.UserService+.*(..))"/>

        <!-- 方式一: 通过定义通知器来实现aop -->
        <aop:advisor advice-ref="beforeLog" pointcut-ref="cutp"/>

        <!-- 方式二: 通过定义切面来实现aop, ref设置Advice(通知) Bean -->
        <aop:aspect ref="timeLog">
            <aop:around method="around" pointcut-ref="cutp"/>
            <aop:before method="before" pointcut-ref="cutp"/>
            <aop:after method="after" pointcut-ref="cutp"/>
        </aop:aspect>
    </aop:config>
</beans>

AOP注解

  1. 开启aop注解

    <aop:aspectj-autoproxy/>
    
  2. 使用aop注解

    @Aspect
    @Before(execution表达式)
    @After, @AfterRunning, @AfterThrowing, @Around
    

Spring整合Mybatis

基本步骤

  1. 编写Dao接口, 以及相应的Mapper.xml

    需要导入 mybatis

    同时注意配置maven的build标签, 解决xml无法打包的问题

  2. 使用spring-jdbc配置数据源(DataSource)

    需要导入 spring-jdbc

  3. 声明dataSource对象和sqlSessionFactory对象

    需要导入 mysql-connector-java, mybatis-spring

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=true"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 这里相当于接替了mybatis-config.xml -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 因为com.xtyuns.dao包中UserDao和UserDao.xml同名, 所以要使用classpath*: -->
        <property name="mapperLocations" value="classpath*:com/xtyuns/dao/*.xml"/>
    </bean>
    
  4. 声明sqlSessionTemplate对象

    <!-- 相当于Mybatis中的sqlSession对象 -->
    <bean id="sessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg ref="sqlSessionFactory"/>
    </bean>
    
  5. 编写测试类并运行测试

    @Test
    public void getUserList() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        SqlSessionTemplate sqlSessionTemplate = context.getBean("sessionTemplate", SqlSessionTemplate.class);
        
        UserDao mapper = sqlSessionTemplate.getMapper(UserDao.class);
        List<User> userList = mapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
    }
    

*** 启用声明式事务

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值