Spring5学习笔记

目录

一、控制反转loC

二、依赖注入DI

2.1 构造器注入 

2.2 Set注入

2.3 扩展方式注入

三、Bean的作用域 Scope

 3.1 单例模式 singleton

3.2 原型模式 prototype

3.3 其他

 四、Bean的自动装配

4.1 byName自动装配

4.2 byType自动装配

4.3 注解自动装配

@Autowired【常用】

@Resource

五、使用注解开发 

六、使用Java的方式配置Spring

七、代理模式

7.1 静态代理 

7.2 动态代理

八、AOP 面向切面编程

8.1 Spring实现AOP

方式一: 使用原生SpringAPI接口

方式二: 自定义切面类实现AOP

方式三:注解实现AOP

九、整合Mybatis

9.1 回顾Mybatis

9.2 Mybatis-Spring

方式一:使用sqlSessionTemplate

方式二:使用SqlSessionDaoSupport

十、声明式事务 

依赖

Spring中的设计模式



Spring是一个轻量级的控制反转(IOC)面向切面编程(AOP)的框架!

一、控制反转loC

控制反转loC(Inversion of Control)是一种设计思想,DI(依赖注入)是实现loC的一种方法。

  • 之前,程序是主动创建对象!控制权在程序猿手上!
  • 使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象

这种思想,从本质上解决了问题,我们程序猿不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专主的在业务的实现上!这是Ioc的原型!

可以通过声明接口来注入具体的实现类实例。方便!

ps: Spring会把所有的bean(对象)创建,即使没有被使用

二、依赖注入DI

bean对象的创建依赖于Spring容器,bean对象的属性由容器注入。

2.1 构造器注入 

(有参构造器)<constructor-arg />

2.2 Set注入

(set+无参构造器)

2.3 扩展方式注入

1.c命名空间(有参构造器) 

xmlns:p="http://www.springframework.org/schema/p"

2.p命名空间(set+无参构造器) 

xmlns:c="http://www.springframework.org/schema/c"

ps: IDEA会报命名空间错误,在设置中忽略即可

三、Bean的作用域 Scope

 3.1 单例模式 singleton

  默认,同一个对象实例user==user2

<bean id="address" class="com.lzq.pojo.Address" p:address="大学" scope="singleton"/>

3.2 原型模式 prototype

  user!=user2

3.3 其他

request、session、application、websocket在web开发中使用。

 四、Bean的自动装配

4.1 byName自动装配

<bean id="cat" class="com.lzq.pojo.Cat"/>
<bean id="dog" class="com.lzq.pojo.Dog"/>

<!--  自动装配
      byName:自动在容器上下文中查找,和类中属性同名的bean id
      byType:自动在容器上下文中查找,和类中属性类型相同的bean
  -->
<bean id="people" class="com.lzq.pojo.People" autowire="byName">
    <property name="name" value="lzq"/>
    <!--        <property name="cat" ref="cat"/>-->
    <!--        <property name="dog" ref="dog"/>-->
</bean>

4.2 byType自动装配

<bean class="com.lzq.pojo.Cat"/>
<bean class="com.lzq.pojo.Dog"/>

<!--  自动装配
      byName:自动在容器上下文中查找,和类中属性同名的bean id
      byType:自动在容器上下文中查找,和类中属性类型相同的bean
  -->
<bean id="people" class="com.lzq.pojo.People" autowire="byType">
    <property name="name" value="lzq"/>
    <!--        <property name="cat" ref="cat"/>-->
    <!--        <property name="dog" ref="dog"/>-->
</bean>

ps: 

byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性名一致

byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性类型一致

4.3 注解自动装配

1.导入约束

xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd"

2.开启注解自动装配

<context:annotation-config/>

@Autowired【常用】

直接在类属性上使用(不需set方法),也可以在set方法上使用 ,按类型(byType)自动匹配,有多个同类的再按名字(byName)匹配,都匹配不上可以用@Qualifier(value = "cat1")绑定bean id

@Autowired
@Qualifier(value = "cat1")
private Cat cat;

@Resource

 默认byName,匹配不上可以用name属性绑定bean id

//假如SmsService接口有两个实现类smsServiceImpl1和smsServiceImpl2
@Resource
private SmsService smsService;    // 报错,byName 和 byType 都无法匹配到 bean
private SmsService smsServiceImpl1;    // 正确注入 SmsServiceImpl1 对象对应的 bean

@Resource(name = "smsServiceImpl1")
private SmsService smsService;// 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)

@Autowired是Spring提供的注解,@Resource是JDK提供的注解。

五、使用注解开发 

在beans.xml中,指定要扫描的包,开启注解

<context:component-scan base-package="com.lzq.pojo"/>
<context:annotation-config/>

@Component

@Scope("singleton")  //作用域
@Component  //等价于<bean id="user" class="com.lzq.pojo.User"/>
public class User {
    @Value("lzq")  //等价于<property name="name" value="lzq"/>
    private String name;
}

六、使用Java的方式配置Spring

  Config.java代替beans.xml。SpringBoot常用

// Config.java

@Configuration  //代表这是一个配置类,就像之前的beans.xml
@ComponentScan("com.lzq.pojo")
@Import(Config2.class)
public class Config {

    @Bean
    public User2 getUser2(){
        return new User2();
    }
}
@Test
public void getUser2(){
    ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
    User2 user = context.getBean("getUser2", User2.class);
    System.out.println(user.getName());
}

七、代理模式

7.1 静态代理 

1.抽象角色接口:租房

public interface Rent {
    void reat();
}

2. 被代理角色:房东 ,要出租房

public class Host implements Rent {
    @Override
    public void reat(){
        System.out.println("房东要出租房子");
    }
}

3.代理角色:中介, 要出租房子,看房,签合同等

public class Proxy implements Rent{
    private Host host;

    public Proxy(Host host) {
        this.host = host;
    }
    @Override
    public void reat() {
        seeHouse();
        host.reat();
        rent2();
    }
    public void seeHouse(){
        System.out.println("中介带客户看房");
    }
    public void rent2(){
        System.out.println("签合同");
    }
}

4.客户:仅通过代理角色租房子

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.reat();
    }
}

因此,代理角色除了租房外,还有看房、签合同等附属操作,横向切面加进去的新业务(AOP) 

7.2 动态代理

了解两个类:interface InvocationHandler 和 class Proxy

//自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Object object;

    public void setObject(Object object) {
        this.object = object;
    }

    //生成代理类
    public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                object.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result = method.invoke(object, args);
        return result;
    }

    //横向插入的新业务!!!
    public void log(String msg){
        System.out.println("调用了"+msg+"方法");
    }
}
public class Client {
    public static void main(String[] args) {
        //被代理类
        Host host = new Host();
        //调用处理程序
        ProxyInvocationHandler handler = new ProxyInvocationHandler();
        handler.setObject(host);
        //动态生成代理类
        Rent proxy = (Rent) handler.getProxy();
        proxy.reat();
    }
}

         

八、AOP 面向切面编程

编程式事务

声明式事务

 通知类型:前置、后置、返回、异常、环绕

8.1 Spring实现AOP

导入依赖

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
  • 方式一: 使用原生SpringAPI接口

增加前置后置日志:

public class Log implements MethodBeforeAdvice, AfterReturningAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
    }

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+",返回结果为"+returnValue);
    }
}

配置AOP

<bean id="userService" class="com.lzq.UserServiceImpl"/>
    <bean id="log" class="com.lzq.Log"/>
    <!--方式一:使用原生Spring API接口-->
    <!--配置aop:需要导入aop的约束-->
    <aop:config>
        <!--切入点execution(要执行的位置)-->
        <aop:pointcut id="pointcut1" expression="execution(* com.lzq.UserServiceImpl.*(..))"/>
        <!--执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut1"/>
    </aop:config>

测试

@Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理代理的是接口 要用UserService接口不能用UserServiceImpl实现类!!!
        UserService userService = context.getBean("userService", UserService.class);
        userService.query();
    }
  • 方式二: 自定义切面类实现AOP

自定义切面类

public class DiyPointCut {
    public void logBefore(){
        System.out.println("执行前");
    }
    public void logAfter(){
        System.out.println("执行后");
    }
}

 配置AOP

<!--方式二:自定义类-->
    <bean id="diy" class="com.lzq.DiyPointCut"/>
    <aop:config>
        <!--自定义切面-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="pointcut2" expression="execution(* com.lzq.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="logBefore" pointcut-ref="pointcut2"/>
            <aop:after method="logAfter" pointcut-ref="pointcut2"/>
        </aop:aspect>
    </aop:config>

测试同上  

  • 方式三:注解实现AOP

切面类

@Aspect
public class AnnotationPointCut {
    @Before("execution(* com.lzq.UserServiceImpl.*(..))")
    public void logBefore(){
        System.out.println("执行前");
    }
    @After("execution(* com.lzq.UserServiceImpl.*(..))")
    public void logAfter(){
        System.out.println("执行后");
    }
}

配置AOP

    <!--方式三:注解实现-->
    <bean id="annotationPointCut" class="com.lzq.AnnotationPointCut"/>
    <!--开启注解支持-->
    <aop:aspectj-autoproxy/>

测试同上 

九、整合Mybatis

9.1 回顾Mybatis

1.编写实体类

2.编写核心配置文件mybatis-config.xml

3.编写接口

4.编写Mapper.xml

5.测试

9.2 Mybatis-Spring

  • 方式一:使用sqlSessionTemplate

1.编写数据源配置

<!--DateSource:使用Spring提供的JDBC数据源替换MyBatis的配置-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC
"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

2. sqlSessionFactory

<!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--绑定MyBatis配置 可有可无-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/lzq/mapper/*.xml"/>
    </bean>

3.sqlSessionTemplate

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--构造器注入-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

4.给接口加实现类 

public class UserMapperImpl implements UserMapper{
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List<User> getUserList() {
        return sqlSession.getMapper(UserMapper.class).getUserList();
    }
}

5.将实现类注入到Spring 

    <bean id="userMapper" class="com.lzq.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

6.测试 

@Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        for (User user : userMapper.getUserList()) {
            System.out.println(user);
        }
    }
  • 方式二:使用SqlSessionDaoSupport

1.2.6.同上

3&4.接口实现类继承SqlSessionDaoSupport

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {

    @Override
    public List<User> getUserList() {
        return getSqlSession().getMapper(UserMapper.class).getUserList();
    }
}

5.将实现类注入到Spring 

    <bean id="userMapper2" class="com.lzq.mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

十、声明式事务 

 开启 Spring 的事务处理功能,使getUserList()方法要执行全执行,不能执行一半!

<!--开启 Spring 的事务处理功能  声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="dataSource"/>
        <!--属性注入也可以-->
        <!--<property name="dataSource" ref="dataSource"/>-->
    </bean>

    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--给哪些方法配置事务-->
        <!--事务传播特性 propagation-->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.lzq.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>
@Override
    public List<User> getUserList() {
        getSqlSession().getMapper(UserMapper.class).addUser(new User(100,"lzq100"));
        getSqlSession().getMapper(UserMapper.class).deleteUserByID(100);
        return getSqlSession().getMapper(UserMapper.class).getUserList();
    }

依赖

        <!--Spring的包-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.14</version>
        </dependency>

        <!--AOP要用-->
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>

        <!--Spring连接数据库要用-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.14</version>
        </dependency>

        <!--整合用到-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>

 资源加载,使src/main/java下的资源可以加载进去,默认在src/main/resources


            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>

Spring中的设计模式

工厂模式

        Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。

单例模式

        线程池、缓存、对话框、注册表、日志对象、充当打印机、显卡等设备驱动程序的对象。

        bean的默认单例模式singleton。

代理模式

        AOP的实现。

        被代理类实现了某接口->JDK代理;未实现->Cglib生成被代理类的子类作为代理。

模板模式

        定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤的实现方式。

        jdbcTemplatehibernateTemplate 等以 Template 结尾的对数据库操作的类。

        Spring使用Callback模式与模板方法模式配合。

观察者模式

        监视器,当一个对象发生改变的时候,这个对象所依赖的对象也会做出反应。

适配器模式

        将一个接口转换成客户希望的另一个接口,使接口不兼容的类可以一起工作。

        Spring AOP 的增强或通知,SpringMVC的HandlerAdapter。

装饰者模式

        DataSource。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值