SpringAOP&整合Mybatis&事务

一、常规的applicationContext.xml配置

<?xml version="1.0" encoding="UTF8"?>
<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/>
<!--导入spring-dao.xml-->
    <import resource="spring-dao.xml"/>

<!--    Mapper对象 往下都是-->


这bean玩意可以在UserMapperImpl类上注解@Component就可以由Spring接管了
同时还有,注意其set方法上要用@Autowired来自动装配
    <bean id="userMapperImpl" class="com.gy.mapper.UserMapperImpl" >
<!--        构造器注入-->
        <constructor-arg name="sqlSessionTemplate" ref="sqlSession"/>
<!--        set方法注入-->
        <property name="sqlSessionTemplate" ref="sqlSession"/>
    </bean>



</beans>

二、动态代理

(1)静态代理

1.静态代理没什么好说的就是一个真实对象(房东)就一个代理对象。

2.但是会有以下情况

3. 如果真实对象变多的时候,代理对象也跟着多起来(因为要实现同一个接口),代码量翻倍。

4.我们希望的是,更多的真实对象时候,我们只需实现真实对象的方法就好,而代理的代码则自动生成,减少开发成本。从此就出现了动态代理。

(2)JDK动态代理

使用原生代码实现,实质是反射机制。

package com.zp.demon01;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * InvocationHandler调用处理程序
 * 写在前面:真实对象和代理对象都要实现/继承共同的规范(抽象类或接口),而真实对象只需要实现纯粹的方法即可
 * 而代理对象可以做额外的任务,比如记录日志等。
 */

public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }
    //生成得到代理类并且实例化代理类
    public Object getProxy(){
//        this.getClass().getClassLoader()获取类加载器,类加载器属于jvm,只有获取到这个类加载器才能将代理类加载到jvm中。
//        target.getClass().getInterfaces() 获取真实对象的实现的所有接口,为了创建代理类时,将这些接口都实现。
//        代理类反编译得到的方法中有一句:
//        super.h.invoke(this, m4, (Object[])null);
//        super表示调用的是父类(Proxy),h表示的是当前ProxyInvocationHandler类的对象,
//        目的为了通过super.h.invoke()调用Proxy子类的invoke(Object proxy, Method method, Object[] args)的方法。
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();//环绕前
        Object result = method.invoke(target, args);
        after();//环绕后
        return result;
    }
}

测试方法: 

    @org.junit.jupiter.api.Test
    public void TestProxy(){
        Host host = new Host();

        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();

        proxyInvocationHandler.setTarget(host);

        Rent proxy = (Rent) proxyInvocationHandler.getProxy();

        proxy.rent();
    }

(2)AOP方式一

导入jar包

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

配置applicationContext.xml

    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.zp.demon03.UserServiceImpl.* (..))"/>
       begin与end为两个自定义类,分别实现了 MethodBeforeAdvice,AfterReturningAdvice接口
       spring通过不同的接口来确定织入的通知执行的顺序
        <aop:advisor advice-ref="begin" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="end" pointcut-ref="pointcut"/>
    </aop:config>

当执行expression="execution(* com.zp.demon03.UserServiceImpl.* (..))指定的方法时,通知会自动的随之执行。

(3)AOP方式二

同样也导org.aspectj包

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

配置applicationContext.xml

    <aop:config>
与方式一相比多了这个<aop:aspect/>,diy是引用自定义的类,里面就写扩展的方法就行(before after)
        <aop:aspect ref="diy"> 
            <aop:pointcut id="point" expression="execution(* com.zp.demon03.UserServiceImpl.* (..))"/>
这两个方法都是通知,方法在自定义的diy类中,
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

三、spring整合mybatis

(1)编写spring-dao.xml文件 内容如下

都是写死的模板,直接套用就好,注意中括号的不同就好

<?xml version="1.0" encoding="UTF8"?>
<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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/context
         https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
         https://www.springframework.org/schema/tx/spring-tx.xsd
          http://www.springframework.org/schema/aop
          http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--使用spring数据源来替代mybatis的配置
      这里使用了spring-jdbc的org.springframework.jdbc.datasource.DriverManagerDataSource

    -->
<!--    配置文件db.properties的导入-->
    <context:property-placeholder location="【db.properties】"/>
<!--    配置并连接数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${db.driver}"/>
        <property name="url" value="${db.jdbcUrl}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
    </bean>

    <!--    sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--        绑定数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--        绑定配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--        扫描Mapper.xml文件-->
        <property name="mapperLocations" value="classpath:【com/gy/mapper/*.xml】"/>
    </bean>

    <!--    SqlSessionTemplate(模板)其实就是sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>


</beans>

(2)MapperImpl实体类的使用

1.方式一

需要手动写sqlseesionTemplate属性并通过@Autowired自动装配获取。

有了sqlseesionTemplate直接.getMapper(接口.class)使用即可

package com.gy.mapper;

import ....

@Component
public class UserMapperImpl implements UserMapper{
    //为了整合的区分 所以以后使用SqlSessionTemplate与sqlSession使用一样

    private final SqlSessionTemplate sqlSessionTemplate;
    //构造器
    @Autowired
    public UserMapperImpl(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSessionTemplate = sqlSessionTemplate;
    }

    @Override
    public List<User> queryUser() {
        UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
        return mapper.queryUser();
    }


}

2.方式二(偷懒)

继承SqlSessionDaoSupport类就可以直接通过getSession来使用

package com.gy.mapper;

import ....;

@Component
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
   //因为sqlSessionFactory在父类是通过set方法注入的,
//但由于没办法给父类(只读)添加@Autowired来自动装配,所以只能重写父类方法,
//最后调用父类set方法
    @Autowired
    @Override
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        super.setSqlSessionFactory(sqlSessionFactory);
    }

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

四、Spring中的事务

(1)导包

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

(2)配置spring-dao.xml

简单,直接将下面的代码,追加到上面的spring-dao.xml的末尾就可以开启事务了。

<!--    配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
     </bean>

<!--    结合AOP实现事务的织入 别人已经写好这个通知,直接使用即可-->
<!--    配置事务通知(增强)注意需要tx的命名空间-->
    <tx:advice id="tx" 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="queryUser" propagation="REQUIRED"/>-->
            <tx:method name="*" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
        </tx:attributes>
    </tx:advice>

<!--配置事务切入点-->
    <aop:config>
<!--dao层 只是对单个数据表的操作,而事务管理的意思是,对多个数据表操作时,有的表成功了,有的没成功,可以促发回滚,所以是在service层 -->
        <aop:pointcut id="txPoint" expression="【execution(* com.gy.service.*.* (..))】"/>

<!--测试事务是否成功时,应该在service层制造错误,而不是在controller层,因为事务织入的是service层-->
        <aop:advisor advice-ref="tx" pointcut-ref="txPoint"/>
    </aop:config>

五、所有jar包(pom.xml)

<?xml version="1.0" encoding="UTF8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>【spring-mybatis】</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <finalName>spring-mybatis</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>7</source>
                    <target>7</target>
                </configuration>
            </plugin>
        </plugins>
        <!--必须配置,属于maven的一个bug,只有这样mapper.xml文件才能编译导出-->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.2</version>
            <scope>test</scope>
        </dependency>
        <!--myBaits-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</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>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

    </dependencies>



</project>

猜你喜欢

转载自blog.csdn.net/qq15347747/article/details/119952838