spring框架 AOP

10、 代理模式

为什么要学习代理模式?因为这就是SpringAOP的底层!【SpringAOP 和 SpringMVC 面试必问】

代理模式的分类:

  • 静态代理
  • 动态代理

10.1 静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真是角色,代理真实角色后,我们一般会做一些附属操作。
  • 客户:访问代理对象的人!

代码步骤:

  1. 接口

    //租房
    public interface Rent {
        public void rent();
    }
    
  2. 真实角色

    //房东
    public class Host implements Rent {
        public void rent(){
            System.out.println("房东要出租房子!");
        }
    }
    
  3. 代理角色

    public class Proxy implements Rent {
        private Host host;
    
        public Proxy() {
        }
        public Proxy(Host host) {
            this.host = host;
        }
    
        public void rent(){
            seeHouse();
            host.rent();
            hetong();
            fee();
        }
        //看房
        public void seeHouse(){
            System.out.println("中介带你看房");
        }
        //签合同
        public void hetong(){
            System.out.println("签合同");
        }
        //收费
        public void fee(){
            System.out.println("收取中介费用");
        }
    }
    
  4. 客户端访问

    public class Client {
        public static void main(String[] args) {
            //房东要租房子
            Host host = new Host();
            //代理,中介帮房东租房子,但是呢?代理角色一般会有一些附属操作!
            Proxy proxy = new Proxy(host);
            proxy.rent();
        }
    }
    

代理模式的好处:

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

缺点:

  • 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低

10.2 加深理解

代码:对应10-demo02

聊聊AOP

10.3 动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的。
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口——JDK动态代理
    • 基于类:cglib
    • java字节码实现:javasisit

需要了解两个类:Proxy:代理;InvocationHandler:调用处理程序

动态代理的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
  • 公共也就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!
  • 一个动态代理类代理类代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要是实现了同一个接口即可!
//自动生成代理类
public class InvocationHandlerProxy 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);
   }

   //处理代理机制
 
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

       Object result = method.invoke(target, args);
       return result;
   }
}

public class Client {
    public static void main(String[] args) {
        //真实角色
        UserServiceImpl userService = new UserServiceImpl();
        //代理角色,暂时没有
        InvocationHandlerProxy proxy = new InvocationHandlerProxy();
        //设置要代理的对象
        proxy.setTarget(userService);
        //动态生成代理类
        UserService proxy1 = (UserService) proxy.getProxy();

        proxy1.add();

    }
}

11、 AOP

11.1 什么是AOP

AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的频率。

image.png

11.2 AOP在Spring中的作用

==提供声明式事务;允许用户自定义切面==

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点,如日志、安全、缓存、事务等等……
  • 切面(ASPECT):横切关注点被模块化的特殊对象,即是一个类。
  • 通知(Advice):切面必须要完成的工作,即是类中的一个方法。
  • 目标(Target):被通知对象。
  • 代理(Proxy):向目标对象应用通知之后创建的对象。
  • 切入点(PointCut):切面通知执行的“地点”的定义。
  • 连接点(jointPoint):与切入点匹配的执行点。
image.png

11.3 使用Spring实现AOP

【重点】使用AOP织入,需要导入一个依赖包。

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>

方式一:使用Spring的API接口【主要SpringAPI接口实现】

 <aop:config proxy-target-class="true">
<!--切入点-->
     <aop:pointcut id="pointcut" expression="execution(* com.service.UserServiceImpl.*(..))"/>
<!--执行环绕-->
     <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
     <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
 </aop:config>

方式二:自定义来实现AOP【主要是切面定义】

 <bean id="diy" class="com.diy.DiyPointcut"/>
    <aop:config proxy-target-class="true">
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="pointcut" expression="execution(* com.service.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

方式三:使用注解实现

  <!--注解支持-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    <!--方式三-->
    <bean id="diyAnnotation" class="com.diy.DiyAnnotation"/>

常用注解:
@Aspect:写下类上,标注类是一个切面
@Before("execution(* com.service.UserServiceImpl.(..))")
@After("execution(
com.service.UserServiceImpl.(..))")
@Around("execution(
com.service.UserServiceImpl.*(..))")
括号里面是切入点

12、 整合Mybatis

步骤:

  1. 导入相关jar包
    • junit
    • Mybatis
    • mysql数据库
    • spring相关的
    • aop织入
    • mybatis-spring【new知识点】
  2. 编写配置文件
  3. 测试

12.1 回忆mybatis

  1. 编写实体类
  2. 编写核心配置文件
  3. 编写接口
  4. 编写Mapper.xml
  5. 测试

12.2 Mybatis-Spring

  1. 编写数据源配置
<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?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</bean>
  1. sqlSessionFactory
<!--定义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/dao/UserMapper.xml"/>
    </bean>
  1. sqlSessionTemplate
 <!--定义sqlSessionTemplet-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
  1. 需要给接口加实现类
public class UserMapperImpl implements UserMapper{
    private SqlSessionTemplate sqlSession;

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

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

    }
}
  1. 将自己写的实现类,注入到Spring中
<bean id="userMapperImpl" class="com.dao.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>
  1. 测试
public class MyTest {

    @Test
    public void test1() throws IOException {

        ApplicationContext context = new ClassPathXmlApplicationContext("spring.config.xml");

        UserMapper userMapperImpl = context.getBean("userMapperImpl", UserMapper.class);

        List<User> users = userMapperImpl.queryUser();

        for (User user : users) {
            System.out.println(user);
        }
    }
}

13、 声明式事务

13.1 回顾事务

  • 把一组业务当成一个业务来做:要么都成功,要么都失败。
  • 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎。
  • 确保完整性和一致性。

事务ADID原则:

  • 原子性
  • 一致性
  • 隔离性
    • 多个业务可能操作同一个资源,防止数据损坏
  • 持久性
    • 事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器中。

13.2 Spring中的事务管理

  • 声明式事务:AOP

配置声明事务

 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="dataSource" />
    </bean>

结合AOP实现事务的织入

<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

配置切入

<aop:config proxy-target-class="true">
       <aop:pointcut id="txPointcut" expression="execution(* com.mapper.*.*(..))"/>
       <aop:advisor advice-ref="transactionInterceptor" pointcut-ref="txPointcut"/>
   </aop:config>
  • 编程式事务:需要在代码中,进行事务的管理

思考:

为什么需要事务?

  • 如果不配置事务,可能存在数据提交不一致的情况
  • 如果我们不在Spring中去配置声明式事务,我们就需要在代码中手动配置事务
  • 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题,不容马虎
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容

  • Spring核心知识 介绍:Spring是一个开源框架,Spring是于2003年兴起的一个轻量级的Java开发框...
    Mark_ZSQ阅读 87评论 0 0
  • AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦...
    程序员日常填坑阅读 941评论 0 0
  • aop的概念 面向切面编程,即横向抽取替代纵向继承。在不修改源代码的前提下增强代码 aop的术语 joinpoin...
    奔跑_孤傲的路上阅读 215评论 0 0
  • AOP编程使用 1.注解版本实现AOP 2.XML方式实现AOP Xml实现aop编程:1) 引入jar文件 【...
    Mark_ZSQ阅读 106评论 0 0
  • 高考临近,时光飞逝,一月过后,便要各奔东西,与诸友同窗三年,相知相交,甚是不舍,特昨此篇,一表感激,二祝大家都能取...
    归风仙人阅读 448评论 4 2