【Spring】Spring AOP学习笔记

Spring AOP

代理模式

  • 为什么要学习代理模式呢
    • Spring AOP的底层是代理模式
  • 代理模式的分类
    • 静态代理
    • 动态代理
一、静态代理
1.客户
package com.kuang.demo1;

//客户 租房子
public class client {
    
    
    public static void main(String[] args) {
    
    
        landlord land=new landlord();
        proxy pro=new proxy(land);
        pro.rent();
    }
}
2.代理角色
package com.kuang.demo1;

//代理角色:中介 代理房东 出租房子 还可以做额外的事情
public class proxy implements rent{
    
    
    private landlord land;

    public proxy() {
    
    
    }

    public proxy(landlord land) {
    
    
        this.land = land;
    }

    public void rent() {
    
    
        land.rent();
        seeHouse();
    }

    public void seeHouse(){
    
    
        System.out.println("中介带你看房!");
    }
}
3.真实角色
package com.kuang.demo1;

//真实角色:房东 出租房子
public class landlord implements rent{
    
    

    public void rent() {
    
    
        System.out.println("房东要出租房子!");
    }
}
4.抽象角色
package com.kuang.demo1;

//抽象角色:租房事件
public interface rent {
    
    
    public void rent();
}
5.静态代理的优缺点
优点:真实角色只关心自己的根本业务;公共业务代理实现;公共业务更容易扩展
缺点:一个真实角色就会产生一个代理角色  开发效率低
二、动态代理
1.客户
package com.kuang.demo2;

public class Client {
    
    
    public static void main(String[] args) {
    
    
        Landlord land=new Landlord();//创建真实角色
        ProxyInvocationHandler pih=new ProxyInvocationHandler();
        pih.setRent(land);//放入真实角色
        Rent proxy=(Rent)pih.getProxy();//动态生成对应的代理类
        proxy.rent();
        proxy.buy();
    }
}
2.代理角色(动态生成代理类)
package com.kuang.demo2;

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

public class ProxyInvocationHandler implements InvocationHandler {
    
    
    private Object target;

    public void setRent(Object target) {
    
    
        this.target = target;
    }
    //生成代理类
    public Object getProxy(){
    
    
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }
    //处理代理实例上的方法调用并返回结果
    //proxy:代理类  method:代理类的调用处理程序的方法对象
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        log(method.getName());
        //本质:利用反射实现
        Object result =method.invoke(target,args);
        return result;
    }
    public void log(String methodName){
    
    
        System.out.println("执行了"+methodName+"方法");
    }

}
3.真实角色
package com.kuang.demo2;

public class Landlord implements Rent{
    
    

    public void rent() {
    
    
        System.out.println("房东要出租房子!");
    }
    public void buy(){
    
    
        System.out.println("房东又买了套新房子!");
    }
}
4.抽象角色
package com.kuang.demo2;

public interface Rent {
    
    
    void rent();
    void buy();
}
5.代码执行结果
执行了rent方法
房东要出租房子!
执行了buy方法
房东又买了套新房子
6.动态代理的优点
一个动态代理  对应某一类业务(中介只负责租房等业务)
一个动态代理可以代理多个类 只要是实现了同一个接口即可(中介可以代理很多房东)

AOP

1.UserService接口
package com.kuang.service;

public interface UserService {
    
    
    void add();
    void delete();
    void update();
    void select();
}
2.UserServiceImpl接口实现类
package com.kuang.service;

public class UserServiceImpl implements UserService{
    
    

    public void add() {
    
    
        System.out.println("增加了一个用户!");
    }

    public void delete() {
    
    
        System.out.println("删除了一个用户!");
    }

    public void update() {
    
    
        System.out.println("更新了一个用户!");
    }

    public void select() {
    
    
        System.out.println("查询了一个用户!");
    }
}
一、使用原生Spring API接口实现AOP
3.Log类
package com.kuang.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {
    
    
    public void before(Method method, Object[] objects, Object o) throws Throwable {
    
    
        System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了!");
    }
}
4.AfterLog类
package com.kuang.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    
    
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
    
    
        System.out.println("执行了"+method.getName()+"方法,返回结果为"+o);
    }
}
5.applicationContext.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"
       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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--注册bean-->
    <bean id="userService" class="com.kuang.service.UserServiceImpl"></bean>
    <bean id="log" class="com.kuang.log.Log"></bean>
    <bean id="afterLog" class="com.kuang.log.AfterLog"></bean>
    <!--方式一:使用原生Spring API接口实现AOP-->
    <!--配置AOP-->
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"></aop:pointcut>
        <!--执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="point"></aop:advisor>
        <aop:advisor advice-ref="afterLog" pointcut-ref="point"></aop:advisor>
    </aop:config>
</beans>
二、使用自定义类实现AOP
3.自定义DiyPointCut类
package com.kuang.DIY;

//方式二:使用自定义类实现AOP
public class DiyPointCut {
    
    
    public void before(){
    
    
        System.out.println("---------方法执行前---------");
    }
    public void after(){
    
    
        System.out.println("---------方法执行后---------");
    }
}
4.applicationContext.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"
       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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--注册bean-->
    <bean id="userService" class="com.kuang.service.UserServiceImpl"></bean>
    <bean id="log" class="com.kuang.log.Log"></bean>
    <bean id="afterLog" class="com.kuang.log.AfterLog"></bean>
    <!--方式二:使用自定义类实现AOP-->
    <bean id="diy" class="com.kuang.DIY.DiyPointCut"></bean>
    <aop:config>
        <!--自定义切面 ref 要引用的类-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
            <aop:before method="before" pointcut-ref="point"></aop:before>
            <aop:after method="after" pointcut-ref="point"></aop:after>
        </aop:aspect>
    </aop:config>
</beans>
三、使用注解方式实现AOP
3.自定义的AnnotationPointCut类
package com.kuang.DIY;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

//方式三:使用注解方式实现AOP

@Aspect//标注这个类是一个切面
public class AnnotationPointCut {
    
    
    @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void before(){
    
    
        System.out.println("---------方法执行前---------");
    }
    @After("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void after(){
    
    
        System.out.println("---------方法执行后---------");
    }
    @Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
    
    
        System.out.println("环绕前");
        System.out.println("签名:"+jp.getSignature());
        //执行方法
        Object proceed=jp.proceed();
        System.out.println("环绕后");
        System.out.println(proceed);
    }
}
4.applicationContext.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"
       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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--注册bean-->
    <bean id="userService" class="com.kuang.service.UserServiceImpl"></bean>
    <bean id="log" class="com.kuang.log.Log"></bean>
    <bean id="afterLog" class="com.kuang.log.AfterLog"></bean>
    <!--方式三:使用注解方式实现AOP-->
    <bean id="annotationPointCut" class="com.kuang.DIY.AnnotationPointCut"></bean>
    <!--开启注解支持-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
四、测试类
import com.kuang.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理代理的是接口(!!!)
        UserService userService=(UserService) context.getBean("userService");
        userService.add();
    }
}

Spring整合Mybatis

1.实体类User
package com.kuang.pojo;

public class User {
    
    
    private int id;
    private String name;
    private String pwd;

    public User() {
    
    
    }

    public User(int id, String name, String pwd) {
    
    
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

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

    public String getPwd() {
    
    
        return pwd;
    }

    public void setPwd(String pwd) {
    
    
        this.pwd = pwd;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}
2.接口UserMapper
package com.kuang.mapper;

import com.kuang.pojo.User;

import java.util.List;

public interface UserMapper {
    
    
    List<User> selectAll();
}
3.UserMapper.xml映射配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.UserMapper">
    <select id="selectAll" resultType="user">
        select * from mybatis.user
    </select>
</mapper>
4.实现类UserMapperImpl
package com.kuang.mapper;

import com.kuang.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImpl implements UserMapper{
    
    
    //  方式一  需要接收传递的sqlSession
    private SqlSessionTemplate sqlSession;

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

    public List<User> selectAll() {
    
    
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        return mapper.selectAll();
    }
}
5.实现类UserMapperImpl2
package com.kuang.mapper;

import com.kuang.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    
    

    public List<User> selectAll() {
    
    
        //  方式二  直接拿到sqlSession
        SqlSession  sqlSession=getSqlSession();
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        return mapper.selectAll();
    }
}
6.applicationContext.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"
       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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <import resource="spring-mybatis.xml"></import>
    <bean id="userMapper" class="com.kuang.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"></property>
    </bean>
    <bean id="userMapper2" class="com.kuang.mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>
</beans>
7.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"
       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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置数据源DataSource:使用Spring的数据源 spring-jdbc-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123qwe"></property>
    </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>
        <property name="mapperLocations" value="classpath*:com/kuang/mapper/*.xml"></property>
    </bean>
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--只能利用构造器注入参数 因为它没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
    </bean>
</beans>
8.mybatis-config.xml配置文件(主要配置别名和设置)
<?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.kuang.pojo"/>
    </typeAliases>
    <!--设置-->
<!--    <settings>-->
<!--        <setting name="" value=""/>-->
<!--    </settings>-->
</configuration>
9.测试类
import com.kuang.mapper.UserMapper;
import com.kuang.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;

public class MyTest {
    
    
    @Test
    public void test() {
    
    
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper=context.getBean("userMapper2", UserMapper.class);
        List<User> userList =userMapper.selectAll();
        for (User user: userList){
    
    
            System.out.println(user);
        }
    }
}

Spring中的事务管理

  • 事务管理的分类

    • 声明式事务
      • 实际是AOP的应用,代码是横切进去的,不影响原有代码
    • 编程式事务
      • 需要在代码中进行事务的管理
      • 项目中一般不用
  • 举个栗子春暖花开(声明式事务)

1.实体类User
package com.kuang.pojo;

public class User {
    
    
    private int id;
    private String name;
    private String pwd;

    public User() {
    
    
    }

    public User(int id, String name, String pwd) {
    
    
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

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

    public String getPwd() {
    
    
        return pwd;
    }

    public void setPwd(String pwd) {
    
    
        this.pwd = pwd;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}
2.UserMapper.xml映射配置文件
package com.kuang.mapper;

import com.kuang.pojo.User;

import java.util.List;

public interface UserMapper {
    
    
    List<User> selectAll();
    int addUser(User user);
    int deleteUser(int id);
}
3.UserMapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.UserMapper">
    <select id="selectAll" resultType="user">
        select * from mybatis.user
    </select>
    <insert id="addUser" parameterType="user">
        insert into mybatis.user (id, name, pwd) values(#{
    
    id},#{
    
    name},#{
    
    pwd})
    </insert>
    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{
    
    id}
    </delete>
</mapper>
4.接口实现类UserMapperImpl
package com.kuang.mapper;

import com.kuang.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    
    

    public List<User> selectAll() {
    
    
        User user=new User(8,"kk","9382820");
        SqlSession  sqlSession=getSqlSession();
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        mapper.addUser(user);
        mapper.deleteUser(8);
        return mapper.selectAll();
    }

    public int addUser(User user) {
    
    
        return getSqlSession().getMapper(UserMapper.class).addUser(user);
    }

    public int deleteUser(int id) {
    
    
        return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
    }
}
5.applicationContext.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"
       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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <import resource="spring-mybatis.xml"></import>
    <bean id="userMapper" class="com.kuang.mapper.UserMapperImpl">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>
</beans>
6.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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--配置数据源DataSource:使用Spring的数据源 spring-jdbc-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123qwe"></property>
    </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>
        <property name="mapperLocations" value="classpath*:com/kuang/mapper/*.xml"></property>
    </bean>
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--只能利用构造器注入参数 因为它没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
    </bean>

    <!--配置声明式事务-->

    <!--开启事务处理功能-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--给哪些方法配置事务 配置事务的传播特性(默认为REQUIRED)-->
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="select*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
    </aop:config>

</beans>
7.mybatis-config.xml配置文件(主要是设置和别名)
<?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.kuang.pojo"/>
    </typeAliases>
    <!--设置-->
<!--    <settings>-->
<!--        <setting name="" value=""/>-->
<!--    </settings>-->
</configuration>
8.测试类
import com.kuang.mapper.UserMapper;
import com.kuang.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class MyTest {
    
    
    @Test
    public void test() {
    
    
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper=context.getBean("userMapper", UserMapper.class);
        List<User> userList =userMapper.selectAll();
        for (User user: userList){
    
    
            System.out.println(user);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/kieson_uabc/article/details/107644557