Spring学习笔记

1、Spring环境搭建

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

1.1、IOC(控制反转)

  • 控制翻转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式,在Spring中实现控制反转的是IoC容器,其实现方式是依赖注入(Dependency Injection)
    讲人话就是:需要对象不用自己手动去创建,Spring帮你来创建,管理,装配。

  • 当需要修改时,只需要修改beans.xml中标签的属性值,不用去修改代码。

  • 之前是主动创建对象,控制权在程序员手上。

  • 使用set之后,是被动接受对象。

2、HelloSpring

POJO中

package com.stjp.pojo;

public class MySpring {
    private String name;

    public String getName() {
        return name;
    }

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

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

beans.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:变量名
		class:new的对象
		property:相当于给对象的属性设值
	-->
    
    
    
    
    <bean id="hello" class="com.stjp.pojo.MySpring">
        <property name="name" value="stjp"/>
    </bean>

    
    <bean id="bye" class="com.stjp.pojo.MyT">
        <property name="mySpring" ref="hello"/>
    </bean>
</beans>
  1. bean:对象

  2. id:变量名

  3. class:new的对象

  4. property:相当于给对象的属性设值

    4.1.value为普通值

    4.2.ref为引用值


Test中

mport com.stjp.pojo.MySpring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        //代表Spring容器,一旦创建所有的bean都会被实例化
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		
        //想使用哪个根据id获取即可
        MySpring hello = (MySpring) context.getBean("hello");
        System.out.println(hello.toString());

    }
}

3、IOC创建对象方式

  • 使用无参构造创建对象,默认。

  • 使用有参构造

法一:下标赋值

 <bean id="hello" class="com.stjp.pojo.MySpring">
       <constructor-arg index="0" value="stjp"/>
  </bean>

法二:类型赋值(不建议使用)

    <bean id="hello" class="com.stjp.pojo.MySpring">
        <constructor-arg type="java.lang.String" value="stjp"/>
    </bean>

法三:直接通过参数名

     <bean id="hello" class="com.stjp.pojo.MySpring">
            <constructor-arg name="name" value="stjp"/>
        </bean>

4、Spring的配置

alias(别名)

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

<alias name="user" alias="user2aaa"/>

bean

  • id:bean的id标识符
  • class:bean对象所对应的类型
  • name:别名,更高级,可以同时取多个别名。

import(同id后面添加的bean会覆盖前面)

一般用于团队开发,它可以将多个配置文件,导入合并为一个

<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
<import resource="beans4.xml"/>

5、DI依赖注入

5.1构造器注入(前面)

5.2 Set注入

  • 依赖:bean对象的创建依赖于容器
  • 注入:bean对象中的所有属性,由容器来注入

复杂环境搭建

import java.util.*;

public class Student {

    private String name;
    private Address address;

    private String[] books;
    private List<String> hobbies;

    private Map<String, String> card;
    private Set<String> game;

    private Properties infor;
    private String wife;

    public Student() {
    }


    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbies=" + hobbies +
                ", card=" + card +
                ", game=" + game +
                ", infor=" + infor +
                ", wife='" + wife + '\'' +
                '}';
    }
}
public class Address {
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

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

beans.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="address" class="com.stjp.pojo.Address">
         <property name="address" value="江门"/>
     </bean>



     <bean id="student" class="com.stjp.pojo.Student">
         <property name="name" value="张三"/>
         <property name="address" ref="address"/>

         <property name="books">
            <array>
                <value>语文</value>
                <value>数学</value>
                <value>英语</value>
            </array>
         </property>


         <property name="hobbies">
             <list>
                 <value>打球</value>
                 <value>跑步</value>
                 <value>游泳</value>
             </list>
         </property>

         <property name="card">
             <map>
                 <entry key="身份证" value="156479833124689"/>
                 <entry key="校园卡" value="21564321"/>
             </map>
         </property>


         <property name="game">
             <set>
                 <value>lol</value>
                 <value>cf</value>
                 <value>dnf</value>
             </set>
         </property>


         <property name="infor">
             <props>
                 <prop key="学生id">1547852</prop>
             </props>
         </property>


         <property name="wife">
             <null/>
         </property>
     </bean>

</beans>

map和properties有差别

6、Bean的自动装配

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

在Spring中有三种装配的方式

  1. 在xml中显示配置
    • Byname自动装配:byname会自动查找,找和自己对象set方法名字对应的id值匹配
    • Bytype自动装配:byType会自动查找,和自己对象属性相同的bean,保证所有的class唯一
  2. 在java中显示配置
  3. 隐式的自动装配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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://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>

6.1、@Autowired

  • 先ByType自动装配找不到再使用ByName自动装配
  • 常与**@Qualifier(value = “xxx”)**一起使用,限定使用id为xxx的bean

相当于省略了两个Property

<bean id="cat" class="pojo/Cat"/>
<bean id="dog" class="pojo/Dog"/>
<bean id="people" class="pojo/People" autowire="byName">
	<property name="name" value="Lewis"/>
    
    
	//<property name="cat" ref="cat"/>自动装配会自动完成,这两行代码可以省略
	//<property name="dog" ref="dog"/>
    
    
</bean>

6.2、 @Resource

  • 先ByType自动装配找不到再使用ByName自动装配
  • 可以用@Resource(name=“xxx”)来限定使用id为xxx的bean

6.3、@Autowired和@Resource的区别

  • @Autowired可以使用在set方法上
  • @Autowired使用在属性上时,可以省略set方法

7、使用注解开发

在spring4之后,必须要保证aop的包导入

使用注解需要导入contex的约束

<?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 http://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/>
    
    //要扫描的包
    <context:component-scan base-package="com.stjp.pojo"/>

</beans>

7.1、@Component!!!

  • 对整个类进行装配。衍生出@Respository,@Service,@Controller,分别用在Dao层、Service层、Controller层的类上,效果一样。所有属性不用写get/set方法
  • 相对于注册了bean
  • bean的id就是这个类名的小写

相当于

<bean id="people" class="com.stjp.pojo.People" />

7.2、@Value

用在属性上,给属性赋值

7.2、小结

  • XML更加万能,适用于任何场合,维护简单方便!
  • 注解不是自己的类使用不了,维护相对复杂
  • xml用来管理bean,注解只完成属性的注入。

8、JavaConfig

Spring的一个子项目,在spring4之后,,他成为了核心功能

两种方式:

  • 使用@Component和@ComponentScan(“pojo”)
  • 使用@Configuration和@bean(主流)

8.1、@Configuration和@bean

@Configuration
public class Config {

    @Bean("user")
    public User getuser(){
        return new User();
    }

}
public class User {

    @Value("stttt")
    private String name;


    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • @Configuration相当于作为xml,作为一个 Spring 的容器来使用,用于完成 Bean 的创建
  • @bean相当于注册一个bean,id默认为方法名

8.2、@Component和@ComponentScan(“pojo”)

@ComponentScan("pojo")
public class Config {

   

}
@Component
public class User {

    @Value("stttt")
    private String name;


    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • @Component相当于注册一个bean,默认id为类名小写
  • @ComponentScan(“pojo”)相当于作为xml并且扫描包

8.3、注意

  • 如果使用注解配置类的方式去做,我们只能通过AnnotationConfigApplicationContext来获取容器

9、代理模式

9.1、静态代理

加多一层,解耦合

9.2、动态代理[*]

java动态代理机制中有两个重要的类和接口InvocationHandler(接口)和Proxy(类),这一个类Proxy和接口InvocationHandler是我们实现动态代理的核心

  • 自己编写并继承InvocationHandler接口的类被称为proxy代理实例的调用处理程序

9.2.1、InvocationHandler接口

  • InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法。

  • 当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用

    /**    * proxy:代理类代理的真实代理对象com.sun.proxy.$Proxy0    * method:我们所要调用某个对象真实的方法的Method对象    * args:指代代理对象方法传递的参数    */    public Object invoke(Object proxy, Method method, Object[] args)        throws Throwable;

9.2.2、Proxy类

  • 用来创建一个代理对象的类
  • 常用newProxyInstance方法创建代理对象
public static Object newProxyInstance(ClassLoader loader,                                             Class<?>[] interfaces,                                             InvocationHandler h)
  • **loader:**类加载器

  • **interfaces:**你要代理的类所实现的接口

  • **h:**一个InvocationHandler对象,表示的是当动态代理对象调用方法的时候会关联到哪一个InvocationHandler对象上,并最终由其调用。

Service接口

public interface Service {    void add();    void delete();}

ServiceImpl类

public class ServiceImpl implements Service{    @Override    public void add() {        System.out.println("使用了add方法");    }    @Override    public void delete() {        System.out.println("使用了delete方法");    }}

代理类调用处理程序类

public class ProxyHandler implements InvocationHandler {
    //获取代理类所实现的接口
    private Service service;

    public void setService(Service service) {
        this.service = service;
    }



        //获取代理类对象
        public Object getProxy(){

            return Proxy.newProxyInstance(this.getClass().getClassLoader(), service.getClass().getInterfaces(),this);
        }




    //代理对象调用代理类方法时会自动进入此方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName());
        Object invoke = method.invoke(service, args);

        return invoke;
    }
}

测试类

public class MyTest {
    public static void main(String[] args) {
        ServiceImpl service = new ServiceImpl();
        //获取代理程序
        ProxyHandler proxyHandler = new ProxyHandler();
        //获取代理类并实现要代理类的接口
        proxyHandler.setService(service);
        Service proxy = (Service) proxyHandler.getProxy();
        
        proxy.add();
    }
}

https://blog.csdn.net/yaomingyang/article/details/80981004

10、AOP[重点]

面向切面编程

AOP的核心是动态代理

  • 横切关注点:横跨多个模块的方法或功能,待加入到业务层实现功能扩充,如日志功能

  • 切面(aspect):横切关注点被模块化的特殊对象,是一个类,即下文中的afterLog类

  • 通知(advice):切面必须完成的工作,即类中的一个方法

  • 目标(target):被通知对象,下文中的UserServiceImpl类的对象

  • 代理(proxy):向目标对象加入通知创建的新对象

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

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


环境搭建:

<dependencies>    <dependency>        <groupId>org.aspectj</groupId>        <artifactId>aspectjweaver</artifactId>        <version>1.9.4</version>    </dependency></dependencies>

beans.xml

<aop:aspectj-autoproxy/>

Service接口

public interface Servic {    void add();    void delete();    void update();    void select();}

ServiceImpl类

public class ServiceImpl implements Servic{    @Override    public void add() {        System.out.println("增加了一个用户");    }    @Override    public void delete() {        System.out.println("删除了一个用户");    }    @Override    public void update() {        System.out.println("更新了一个用户");    }    @Override    public void select() {        System.out.println("查询了一个用户");    }}

10.1、使用Spring API接口实现

需要继承Spring提供的AOP接口【AfterReturningAdvice、MethodBeforeAdvice】

<!--aop配置--><aop:config>    <!--要切的类-->    <aop:pointcut id="poincut" expression="execution(* com.stjp.Service.ServiceImpl.*(..))"/>    <!--用什么方法切,切到哪里-->    <aop:advisor advice-ref="logafter" pointcut-ref="poincut"/>    <aop:advisor advice-ref="logabefore" pointcut-ref="poincut"/></aop:config>

after类

public class logAfter implements AfterReturningAdvice {


    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println(method.getName()+o);
    }
}

before类

public class logBefore implements MethodBeforeAdvice {


    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName()+method.getName()+"执行前");
    }
}

10.2、使用自定义类实现

<aop:config>
        <!-- 自定义切面-->
        <aop:aspect id="diy" ref="afterorbefore">

            <!-- 要切的类-->
            <aop:pointcut id="poincut" expression="execution(* com.stjp.Service.ServiceImpl.*(..))"/>
            
            <!--切的方式-->
            <aop:after method="after" pointcut-ref="poincut"/>
            <aop:before method="before" pointcut-ref="poincut"/>

        </aop:aspect>

    </aop:config>

自定义类

public class afterOrBefore {

   
    public void before(){
        System.out.println("使用方法前");
    }

    
    public void after(){
        System.out.println("使用方法后");
    }
}

10.3、使用注解实现

@Aspect//说明这是一个切面
public class afterOrBefore {

    @Before("execution(* com.stjp.Service.ServiceImpl.*(..))")
    public void before(){
        System.out.println("使用方法前");
    }

    @After("execution(* com.stjp.Service.ServiceImpl.*(..))")
    public void after(){
        System.out.println("使用方法后");
    }
}

11、Mybatis和Spring整合

文档: https://mybatis.org/spring/zh/

  • 整合核心就是把Mybatis中的sqlSessionFactory和sqlSession交给Spring管理
  • 可以使得Service层更加灵活!!!

环境配置

<dependencies>
        <!--JDBC-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

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


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



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





        <!--AOP-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>

    </dependencies>


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

Spring-Mybatis.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">

        <!--DataSource:使用Spring的数据源DriverManagerDataSource代替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?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=true"/>
            <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:mybatisConfig.xml"/>
        </bean>


        <!--SqlSessionTemplate就是我们使用的SQLSession-->
        <bean id="sqlSesion" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>





</beans>

方法一:

userMapperImpl类【实际上是service层】

public class userMapperImpl implements userMapper{


    private SqlSessionTemplate SqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        SqlSession = sqlSession;
    }

    @Override
    public List<user> getUSer() {

        userMapper mapper = SqlSession.getMapper(userMapper.class);
        List<user> list = mapper.getUSer();


        return list;
    }
}


**方法二:**使用SqlSessionDaoSupport

userMapperImpl类【实际上是service层】

public class userMApperImpl2 extends SqlSessionDaoSupport implements userMapper{
    @Override
    public List<user> getUSer() {
        return getSqlSession().getMapper(userMapper.class).getUSer();
    }
}

Spring容器上注册bean

  <bean id="userMapper2" class="com.stjp.Mapper.userMApperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

12、Spring声明式事务

12.1、回顾事务

  • 把一组业务当成一个业务来做,要么都完成,要么都失败
  • 确保完整性和一致性

事务的ACID原则:

  • 一致性
  • 原子性
  • 隔离性
  • 持久性

12.2、Spring中的事务管理

  • 声明式事务管理:AOP
  • 编程式事务管理

第一步:

<!--声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="datasource" />
    </bean>

第二步:

<!--结合aop实现事务置入-->
    <!--配置事务的类-->
    <tx:advice id="tx1" transaction-manager="transactionManager">
        <!--给哪些方法配置事务-->
        <!--配置事务的传播特性-->
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="*" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="txpointxut" expression="execution(* com.mapper.*.*(..))"/>
        <aop:advisor advice-ref="tx1" pointcut-ref="txpointxut"/>
    </aop:config>

注意:动态代理代理的是接口!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值