Spring复习——B站

IOC创建对象方式

IOC默认创建对象方式:使用无参构造方法,也可以使用构造器方法注入(有参构造)

有参构造里有三种方法:

  1. 索引注入
  2. 参数类型注入:基本数据类型直接写:int,引用数据类型写全路径:java.lang.String,如果存在多参数同类型,则不采用!
  3. 参数名注入:通过name和value来指定

在配置文件加载时,spring容器中托管的所有类就已经被初始化了

Spring配置

alias:别名
bean:配置javabean,其中id为唯一标识符,name为别名,用逗号或空格分号分隔,class指定托管类
import:用于团队开发,导入合并多个配置文件,会自动合并相同的配置

DI依赖注入

  1. 构造器注入
<bean id="hello" class="com.xiaopi3.pojo.Hello">
    <constructor-arg name="name" value="pppp"/>
    <constructor-arg name="age" value="1212"/>
</bean>
  1. set注入
<bean id="hello" class="com.xiaopi3.pojo.Hello">
   	<property name="name" value="pp"/>
    <property name="age" value="12"/>
</bean>
  1. 其他
    扩展注入:引入p空间和c空间。
  • p空间:可以在标签属性上直接注入对象属性,对应set注入
  • c空间:对应构造器注入,必须提供有参构造才行
<bean id="hello" class="com.xiaopi3.pojo.Hello" p:name="ppp" p:age="15"></bean>

注入方式有:xml配置和注解配置。可注入的类型:bean | ref | idref | list | set | map | props | value | null

bean作用域

singleton:单例
prototype:原型,每次获取bean都是新对象
request:request全局唯一
session:session全局唯一
application
websocket

bean xml自动装配

三种装配方式:xml、java、隐式,隐式方式为自动装配

在bean标签中:autowire="byName"查找装配同该bean中set后名字匹配的配置bean。autowire="byType"查找类型相同的进行装配。

<bean id="son" class="com.xiaopi3.Son" p:name="myson" p:age="1"></bean>
<bean id="dad" class="com.xiaopi3.Dad" autowire="byName"></bean>

而Dad中:

@Data
public class Dad {
    private String name;
    private int age;
    private Son son;
}

bean 注解自动装配

使用注解需要满足2条件:

  1. 导入约束
    多了一个context约束!
  2. 启用注解
<?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>
  1. 在java中需要注入的属性前加上注解即可

@Autowired:会自动反射进行注入,不用再写set方法了,默认byType注入,多个匹配则按名称匹配
@Autowired(required = false):当前bean未找到时则不进行注入操作!
@Qualifier:指定注入对象的名字,用来与@Autowired搭配,byName

@Resource:该注解是javax注解,作用差不多,组合,包含好几个功能,默认byName,可以指定byType,多个匹配按类型匹配

@Nullable:加在参数上,标记该参数可以为null

注解使用

注解开发必须

  1. 导入AOP包
  2. 需要导入context约束
  3. 需要启动自动装配
  4. 需要启动包扫描:包扫描为了启用除了自动装配以外的注解!

例如:
在这里插入图片描述
@Component:放在bean上,表示装配该bean
@Value:注入值,放在属性上或set方法上
@Repository:仓库,放在dao的类上,功能同@Component
@Service:放在service层,功能同@Component
@Controller:放在controller层,功能同@Component
@Scope:作用域,放在bean上,限定范围

最佳实践:xml只用来管理bean,注解只用来完成属性的注入

Java类作为配置

使用java类来作为配置类,等价于xml配置文件:

// 配置
@Configuration
@ComponentScan(basePackages = "com.acme")
@Import(AppConfig2.class)
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

// 调用
public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

注意:装配bean的两种方式:1.配置类里面加了@Bean;2.配置类配置了扫描包注解@ComponentScan
注意:@Import注解可以导入其他的配置类,相当于合并配置文件

AOP

代理模式

静态代理

优点:
使真实实体功能更纯粹、可以在代理类中增强一些其他功能、可以集中管理一些附加功能
缺点:
一个真实角色就产生一个代理角色,容易产生过多的代理角色,降低开发效率

动态代理

  1. 基于接口:jdk动态代理
  2. 基于类:cglib
  3. 基于字节码:javassist
    优点:静态代理有的都有+代理的是一个接口,实用性更广
UserService userService =  new UserServiceImpl();// 此处只要new一个实现了UserService的实现类即可动态改变生成的代理类
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService);
UserService proxy = pih.getProxy();
proxy.add();

spring aop实现:xml配置

使用spring必须要导入一个织入的包:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
    <scope>runtime</scope>
</dependency>

1. 切入点+通知:pointcut+advisor

这种方式功能强,可以获取被增强方法各种属性!!!

  1. 导入aop依赖包
  2. 编写增强类:依据增强类型实现不同的增强接口即可
//dao
public interface UserDao {
    public void add();
    public void delete();
}
//daoimpl
public class UserDaoImpl implements UserDao {
    @Override
    public void add() {
        System.out.println("新增用户");
    }

    @Override
    public void delete() {
        System.out.println("删除用户");
    }
}
//增强类
public class LogBefore implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"类,执行了该方法:"+method.getName());
    }
}
  1. 配置xml
<bean id="userDao" class="com.xiaopi3.dao.UserDaoImpl"/>
<bean id="logBefore" class="com.xiaopi3.log.LogBefore"/>
<aop:config>
    <aop:pointcut id="p1" expression="execution(* com.xiaopi3.dao.*.*(..))"/>
    <aop:advisor advice-ref="logBefore" pointcut-ref="p1"/>
</aop:config>
  1. 获取需要注入的类,调用方法
    @Test
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        userDao.add();
        userDao.delete();
    }

2. 切入点+切面:pointcut+aspect

这种方式使用简单,功能简单!

  1. 导入aop包
  2. 编写切面类
public class LogAspect {
    public void before(){
        System.out.println("前置方法");
    }
    public void after(){
        System.out.println("后置方法");
    }
}
  1. 配置xml
    <bean id="logAspect" class="com.xiaopi3.log.LogAspect"/>

    <aop:config>
        <aop:aspect ref="logAspect">
            <aop:pointcut id="p1" expression="execution(* com.xiaopi3.dao.*.*(..))"/>
            <aop:before method="before" pointcut-ref="p1"/>
            <aop:after method="after" pointcut-ref="p1"/>
        </aop:aspect>
    </aop:config>

  1. 执行测试
    @Test
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        userDao.add();
        userDao.delete();
    }

3. 注解实现

注解实现需要导入aspctj包:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.6</version>
</dependency>
  1. 编写增强类
@Aspect
public class LogAspectAnnotation {

    @Before("execution(* com.xiaopi3.dao.*.*(..))")
    public void logBefore(){
        System.out.println("log before====>>");
    }
}
  1. 配置xml
    需要开启环绕注解支持
    <aop:aspectj-autoproxy/>

    <bean id="userDao" class="com.xiaopi3.dao.UserDaoImpl"/>
    <bean id="logAspect" class="com.xiaopi3.log.LogAspectAnnotation"/>
  1. 执行测试类
    @Test
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        userDao.add();
        userDao.delete();
    }

注意:代理配置中<aop:aspectj-autoproxy expose-proxy="false"/>默认是false,如果选择true则使用cglib代理模式
在这里插入图片描述

事务

ACID原则:原子性、一致性、隔离性、持久性
spring支持两种事务:声明式和编程式,编程式由于侵入代码太多,不常采用。

使用aop配置事务

这里将所有mapper下的方法全部加入了事务
在这里插入图片描述
事务传播特性一共有六种:默认REQUIRED,表示支持事务,如果没有就新建。
PROPAGATION_REQUIRED–支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS–支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY–支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW–新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED–以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER–以非事务方式执行,如果当前存在事务,则抛出异常。

整合

整合mybatis

导包:junit、mysql、spring-webmvc、mybatis、spring-jdbc、aspectjweave、mybatis-spring

1. mybatis单独回顾

  1. 编写实体类pojo
@Data
public class User {
    public String name;
    public int age;
}
  1. 编写实体类dao接口方法mapper类(等价于dao层的接口类)
public interface UserMapper {
    public void insert(User user);
    public List<User> select();
}
  1. 编写对应接口的配置文件xml,这里包括两个方法,插入和查询
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaopi3.mapper.UserMapper">
    <select id="select" resultType="user">
        select * from ooo.user;
    </select>

    <insert id="insert" parameterType="user">
        insert into ooo.user (name,age) values(#{name},#{age});
    </insert>
</mapper>
  1. 编写mybatis-config.xml核心配置文件,typeAliases用于定位pojo包,类似自动装配
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.xiaopi3.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ooo?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/xiaopi3/mapper/UserMapper.xml"/>
    </mappers>
</configuration>
  1. 测试
    注意:openSession中true表示启用事务自动提交
	@Test
    public void test01() throws IOException {
        InputStream rin = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(rin);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user1 = new User();
        user1.setAge(13);
        user1.setName("pp");
        mapper.insert(user1);

        List<User> select = mapper.select();
        for (User user : select) {
            System.out.println(user);
        }
        sqlSession.close();

问题一:找不到配置文件
将工程下pom下的配置新增如下,该配置表示对某个目录下的xml文件不过滤,进行输出。

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

2. mybatis整合

参考:mybatis.org

  1. 导包:junit、mysql、spring-webmvc、mybatis、spring-jdbc、aspectjweave、mybatis-spring

  2. 为了消除原先在测试类中的SqlSessionFactorySqlSession,使用spring来注入,需要配置这两个bean,分别对应:
    SqlSessionFactory --> org.mybatis.spring.SqlSessionFactoryBean,该类需要数据源,所以在spring中配置数据源,mybatis中就不用配置了

    SqlSession --> org.mybatis.spring.SqlSessionTemplate

    然后spring特有的,对接口的调用需要有个实现类,所以需要新加一个实现类!

    <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/ooo?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/xiaopi3/mapper/*.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
    
    <bean id="userMapper" class="com.xiaopi3.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>
    

    原来只需要UserMapper.java UserMapper.xml,现在需要再加一个UserMapperImpl.java
    实现类:实现类需要调用dao层数据,需要sqlSession的注入,注入必须要set方法

    public class UserMapperImpl implements UserMapper{
    	private SqlSession sqlSession;
    
        public void setSqlSession(SqlSession sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        @Override
        public void insert(User user) {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.insert(user);
        }
    
        @Override
        public List<User> select() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.select();
        }
    }
    

    注意:在spring配置文件中配置了的东西需要在mybatis中进行删除!删完后只留下这个(也可以全在spring中配置,将mybatis配置文件删掉)

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <typeAliases>
            <package name="com.xiaopi3.pojo"/>
        </typeAliases>
    
    </configuration>
    
  3. 测试

    @Test
    public void test01() throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);

        User user1 = new User();
        user1.setAge(13);
        user1.setName("pp");
        userMapper.insert(user1);

        List<User> select = userMapper.select();
        for (User user : select) {
            System.out.println(user);
        }
    }

3. SqlSessionDaoSupport自动生成sqlSession

在MapperImpl类上继承该类,则可以直接使用getSession来获取sqlSession,同时配置文件中使用该类后可以舍弃掉SqlSessionTemplate类,直接注入SqlSessionFactory即可:

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
    @Override
    public void insert(User user) {
        getSqlSession().getMapper(UserMapper.class).insert(user);
    }

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

配置文件中:

    <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/ooo?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/xiaopi3/mapper/*.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

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

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

测试:同上不变

再加上事务处理

在MapperImpl中加入事务处理操作

  1. 在配置文件中配置好事务
<?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:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
">

    <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/ooo?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/xiaopi3/mapper/*.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

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

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

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

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="insert"/>
        </tx:attributes>
    </tx:advice>
    
    <aop:config>
        <aop:pointcut id="p1" expression="execution(* com.xiaopi3.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="p1"/>
    </aop:config>

</beans>
  1. mybatis配置文件配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.xiaopi3.pojo"/>
    </typeAliases>

</configuration>
  1. Dao实现类,省略Dao接口和pojo类
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
    @Override
    public void insert(User user) {
        getSqlSession().getMapper(UserMapper.class).insert(user);
        System.out.println(1/0);// 此处肯定报错!
    }

    @Override
    public List<User> select() {
        return getSqlSession().getMapper(UserMapper.class).select();
    }
}
  1. 测试类
    @Test
    public void test02() throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);

        User user1 = new User();
        user1.setAge(18);
        user1.setName("002");
        userMapper.insert(user1);

        List<User> select = userMapper.select();
        for (User user : select) {
            System.out.println(user);
        }
    }

结果由于insert方法报错,事务回滚了,虽然程序依旧报错,但是数据库数据没变化

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值