Welcome to 发呆鱼.|

发呆鱼

园龄:3年4个月粉丝:1关注:0

spring 入门学习笔记

spring 入门学习笔记

入门笔记,尚未学习完,后续进行补充。

新手上路,望斧正

1 简介

spring 理念:使现有技术更加容易使用,本身是一个大杂烩,整合了现有框架。

ssh: struct2+spring+hibernate

ssm:springmvc+spring+mybatis

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.13</version>
</dependency>

优点

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

2 IOC 理论

2.1 IOC初步体会

​ 当编写一个复杂的 Java 应用程序时,应用程序类应该尽可能的独立于其他的 Java 类来增加这些类可重用可能性,当进行单元测试时,可以使它们独立于其他类进行测试。依赖注入(或者有时被称为配线)有助于将这些类粘合在一起,并且在同一时间让它们保持独立。

private UserDao userDao;

public void setUserDao(UserDao userDao){
    this.userDao=userDao;
}

使用一个set 的接口,让程序不再具有主动性,而是变成被动的接收对象。程序不再去管理对象的创建,系统耦合性降低,可以更加专注在业务上实现

<?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">

    <bean id="UserDao" class="com.fadaiyu.dao.UserDaoImpl">
        <!-- collaborators and configuration for this bean go here -->
        <property name="str" value="spring"/>
    </bean>

    <bean id="UserDaoMysqlImpl" class="com.fadaiyu.dao.UserDaoMysqlImpl"/>
    
    <bean id="UserServiceImpl" class="com.fadaiyu.service.UserServiceImpl">
        <!--
            ref 引用spring 容器中创建的对象
            value 是引用具体的值
        -->
        <property name="userDao" ref="UserDaoMysqlImpl"/>
    </bean>
    
    <!-- more bean definitions go here -->

</beans>
//拿到ApplicationContext 拿到spring 容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//直接获取一个bean
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
userServiceImpl.getUser();

程序不需要再new 一个对象,而是由spring 进行创建管理装配。至于想用那种UserDao的实现方式,仅需要修改一配置文件即可。如果添加更多的实现方式,只需要在配置文件中添加一个bean ,而代码无需改动。

2.2 IOC 创建对象的过程

image-20220126185143492

在走到getBean的时候创建的对象。

spring 默认使用无参构造器,有参构造器见Core Technologies (spring.io)的1.4.1

2.3 set注入方式

<?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">

    <bean id="Adress" class="com.fadaiyu.dao.Adress" name="adress">
        <property name="address" value="china"/>
    </bean>

   <bean id="Student" class="com.fadaiyu.dao.Student" name="student">
       <!--第一种,普通类型注入-->
       <property name="name" value="fadaiyu"/>

       <property name="adress" ref="Adress">

       </property>

       <!--数组-->
       <property name="books">
           <array>
               <value>11111</value>
               <value>22222</value>
           </array>
       </property>

       <!--list 注入-->
      <property name="hobbies">
          <list>
              <value>aaaaa</value>
              <value>bbbbb</value>
          </list>
      </property>

       <!--map-->
       <property name="card">
           <map>
               <entry key="qqq" value="qqqq"/>
               <entry key="www" value="www"/>
           </map>
       </property>

       <property name="games">
           <set>
               <value>lol</value>
               <value>cf</value>
           </set>
       </property>

       <!--null-->
       <property name="wife">
           <null/>
       </property>

       <property name="info">
           <props>
               <prop key="学号">77777</prop>
               <prop key="pwd">123</prop>
           </props>
       </property>

   </bean>

</beans>

2.4 p命名和c命名

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="User" class="com.fadaiyu.dao.User" p:name="fadaiyu" p:age="12"/>

    <bean id="User2" class="com.fadaiyu.dao.User" c:age="17" c:name="fadaiyu2"/>
</beans>

**要导入相关依赖 **

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

2.5 作用域

image-20220126214837822

2.6 bean 的自动装配

自动装配是spring满足bean依赖一种方式,spring会在上下文中自动寻找,并给bean装配属性。

spring 中有三种装配方式:

  • 在xml 中配置I(即上面的方式)
  • 在java 中显示配置
  • 隐式的自动装配bean
<bean id="People" name="pople" class="com.fadaiyu.dao.People" autowire="byName">
    <property name="name" value="fadaiyu"/>
</bean>

按属性名自动装配。Spring寻找与需要自动连接的属性同名的bean。需要保证id 唯一

<bean id="People" name="pople" class="com.fadaiyu.dao.People" autowire="byType">
    <property name="name" value="fadaiyu"/>
</bean>

如果容器中恰好存在一个该属性类型的bean,则允许该属性被自动连接。

2.7 通过注解装配

导入依赖

<?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"
    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">

    <context:annotation-config/>

</beans>

在属性上加上 @Autowired,可以配合@qualifier(value=xxx)来指定唯一的bean对象注入。通过bytype 方式

@Resource

@Resource(name = "Dog")
private Dog dog;

通过byname 方式,如果找不到名字,再使用bytype

@Component

组件,放在类上,说明这个类被spring 管理了,就是bean

  • dao [@Repository]
  • service [@Service]
  • controller [@Controller]

@Value

给属性注解,可以放在属性上,也可以放在set上

3 AOP

3.1静态代理

角色分析:

  • 抽象角色:一般使用接口或者抽象类来解决。
  • 真实角色:被代理的角色。
  • 代理角色:代理真实角色,代理真实角色后一般会做一些附属操作。
  • 客户:访问代理对象的人。
//租房
public interface Rent {
    //出租房屋
    public void rent();
}

//房东,是真实角色,它要出租房屋
public class LandLord implements Rent{

    @Override
    public void rent() {
        System.out.println("房东出租房屋");
    }
}
//中介
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TheMediation implements Rent{
    private LandLord landLord;

    @Override
    public void rent() {
        //帮助房东租房子
        seeHose();
        contract();
        charge();
        landLord.rent();
    }

    public void seeHose(){

        System.out.println("看房");
    }

    public void contract(){
        System.out.println("签合同");
    }

    public void charge(){
        System.out.println("收费");
    }
}
//要租房子的客户
public class Customer {
    public static void main(String[] args) {
        //房东要出租房子,将房子交给中介,房东只用提供房子,中介帮助房子完成其他操作
        TheMediation mediation = new TheMediation(new LandLord());

        //用户只用去找中介,不用直接面对房东
        mediation.rent();
    }
}

代理模式的好处:

  • 可以让真实角色操作更加纯粹,不用去关注一些公共业务。
  • 公共业务交给代理角色,实现业务分工。
  • 公共业务发生扩展,方便集中管理。

3.2 动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理对象是动态生成的,不是直接写好的。
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口: jdk动态代理
    • 基于类: cglib
    • java 字节码:javasist
public class ProxyInvocationHandler implements InvocationHandler {

    private Object target;

    public void setTarget(Object target){
        this.target=target;
    }

    //得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this );
    }
    

    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     
        //动态代理的本质,就是使用反射机制实现
        Object invoke = method.invoke(target, args);
        return invoke;
    }
    
}
public class Client {

    public static void main(String[] args) {
        //真实角色
        UserServiceImpl userService=new UserServiceImpl();
        //代理角色
        ProxyInvocationHandler pih=new ProxyInvocationHandler();
        //设置要代理的对象
        pih.setTarget(userService);
        //生成代理类  ##注意:动态代理,代理的是接口
        UserService userProxy=(UserService)pih.getProxy();

        userProxy.addUser();

    }
}

动态代理的好处:一个动态代理类代理的是一个接口,一般就是对应的一类业务,一个动态代理可以代理多个类,只要是心啊了同一个接口。

3.3 aop 实现

添加依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
</dependency>
  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 ....

  • 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。

  • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。

  • 目标(Target):被通知对象。

  • 代理(Proxy):向目标对象应用通知之后创建的对象。

  • 切入点(PointCut):切面通知 执行的 “地点”的定义。

  • 连接点(JointPoint):与切入点匹配的执行点。

3.3.1 使用原生的spring api

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

    <!--注册bean-->
    <bean id="userService" class="com.fadaiyu.service.UserServiceImpl"/>

    <bean id="befoLog" class="com.fadaiyu.log.Log"/>
    <bean id="afterLog" class="com.fadaiyu.log.AfterLog"/>

    <!--方式一 使用原生的spring api-->
    <!--配置aop-->
    <aop:config>
        <!--切入点:expression表达式:execution(要执行的位置,,,)-->
        <aop:pointcut id="pointcut" expression="execution(* com.fadaiyu.service.UserServiceImpl.*(..))"/>

        <!--执行环绕-->
        <aop:advisor advice-ref="befoLog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

</beans>
public void test1(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContex.xml");

    // ## 注意 动态代理代理的是接口
    UserService userService=context.getBean("userService",UserService.class);

    userService.addUser();
}

3.3.2 自定义实现

<!--方法二;自定义类-->
<bean id="diypoint" class="com.fadaiyu.diy.DiyPointCut"/>
<aop:config>
    <!--自定义切面。 ref 要引用的类-->
    <aop:aspect ref="diypoint">
        <!--切入点-->
        <aop:pointcut id="point" expression="execution(* com.fadaiyu.service.UserServiceImpl.*(..))"/>

        <!--通知-->
        <aop:before method="beforePoint" pointcut-ref="point"/>
        <aop:after method="afterPonit" pointcut-ref="point"/>
    </aop:aspect>
</aop:config>

3.3.3 使用注解实现

<!--方式三:开启注解支持, jdk(默认) cglib(proxy-target-class="true") -->
<aop:aspectj-autoproxy />
@Aspect  //标注这个类是一个切面
public class AnnPoint {

    @Before("execution(* com.fadaiyu.service.*.*(..))")
    public void before(){
        System.out.println("前------------");
    }

    @After("execution(* com.fadaiyu.service.*.*(..))")
    public void after(){
        System.out.println("------------后");
    }
    @Around("execution(* com.fadaiyu.service.*.*(..))")
    public void around(ProceedingJoinPoint pj) throws Throwable {
        System.out.println("环绕前");
        Object procced=pj.proceed();

        System.out.println("环绕后");


    }
}

4 整合mybatis

添加依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.13</version>
</dependency>


<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.27</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.14</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.6</version>
</dependency>

配置过滤

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

spring 接管mybatis

 <!--datasource 使用spring 的数据源替换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/myemployees?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>

    </bean>

    <!--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/fadaiyu/mapper/*.xml"/>

    </bean>

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--只能使用构造器注入sqlSessionFactory,没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <bean id="jobsMapperImpl" class="com.fadaiyu.mapper.JobsMapperImpl">
        <property name="sqlSessionTemplate" ref="sqlSession"/>
    </bean>

也可以使用简化操作,继承SqlSessionDaoSupport

public class JobsMapperImpl2 extends SqlSessionDaoSupport implements JobsMapper{
    @Override
    public List<Jobs> selectAll() {
        return getSqlSession().getMapper(JobsMapper.class).selectAll();
    }
}


  1. 跟随B站 遇见狂神说 学习spring 的入门笔记。 ↩︎

本文作者:发呆鱼

本文链接:https://www.cnblogs.com/dyiblog/articles/15854039.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   发呆鱼  阅读(19)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起