Spring总结(4)

Spring面向切面AOP编程
1. AOP编程原理

使用背景

  • 需要在原有的应用功能模块增加额外的辅助功能,但并不是所有的应用功能模块所必需的
  • 使用面向对象继承或者依赖技术增加辅助功能,会导致部分甚至所有的应用功能模块声明的类都会与辅助功能类在代码上存在耦合关系
  • 使用代理委托方式,存在对委托对象进行复杂调用,容易导致原来的功能模块出现问题

AOP切面作用

  • 可以将上述增加辅助功能的问题转换为一个特殊类,集中处理,无须分散到各处的应用模块中
  • 当前的特殊类只关注该辅助功能的实现,更为集中也便于维护

AOP原理

AOP可以比喻为我们要完成的一项任务工作, 一般做任何一项任务都具备目标,任务分解以及利用现有的工具资源来帮助任务推进,简言之可以将AOP对应的概念理解如下:

  • 目标: 最终要完成任务的目标 – AOP的通知Advice,设定的程序目标
  • 工具: 完成一项任务的目标我们需要借助一项工具来帮助我们更有效地完成 – AOP的连接点,提供信息/方法
  • 任务分解: 任务比较多的时候我们可以采用任务分解的方式来完成,将任务逐一划分为可执行的区域 – AOP的切点,类似任务分解的区域,也就是where
  • 最后,就是在做一项任务之前,我们都知道要完成这项任务的目标以及如何去划分任务,这个就是AOP的切面,包含了通知和切点,定义任务的全部内容(准确地说,还包含工具提供的信息在里面)

AOP 术语

  • 切面: 定义要完成一项任务的全部内容,即声明一个切面的类定义任务内容信息
  • 通知: 定义要完成任务的目标,即在一个切面类下的目标方法
    • 前置通知(Before):在目标方法被调用之前调用通知功能;
    • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
    • 返回通知(After-returning):在目标方法成功执行之后调用通知;
    • 异常通知(After-throwing):在目标方法抛出异常后调用通知;
    • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
  • 切点: 定义要在什么地方执行,即在一个切面类下的目标方法中,告诉目标方法要在什么地方执行
  • 连接点: 定义要完成任务的工具,即从程序角度而言,是利用应用程序中已有的功能为完成任务提供辅助,从我们定义的业务而言,是指我们原有的业务功能
  • 引入: 在无须修改类的情况下, 向现有的业务功能的类添加方法或者属性, 让它们具有新的行为和状态
  • 织入: 是把切面应用到目标对象并创建新的代理对象的过程.切面在指定的连接点被织入到目标对象中
    • 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的
    • 类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ 5的加载时织入(load-timeweaving,LTW)就支持以这种方式织入切面
    • 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面
2. AOP编程创建切面

AOP 基于注解的方式

Spring AOP是基于方法去做增强,也就是在类或对象的方法上做增强,需要区分AOP引入

  • 定义连接点
/**
 * 定义连接点 -- 业务处理功能
 * 项目是基于SpringBoot
 */
 // AnnPerformance.java
public interface AnnPerformance {

    public void perform();
}

// 实现类AnnPerformanceImpl.java
@Component
public class AnnPerformanceImpl implements AnnPerformance {

    @Override
    public void perform() {
        System.out.println("AnnPerformanceImpl performance ... ");
    }
}
  • 定义切面
// AnnAudience.java
/**
 * 使用注解定义一个切面类,包含定义通知以及切点,使用注解的切面声明必须能够为通知类添加注解,为此要做到这点,必须有源码
 * 使用原则,基于注解的配置优于Java的配置,基于Java的配置优于xml的配置
 * @Aspect 使用该注解,Spring会动态为该Bean以及对应的目标bean创建代理对象,通过代理对象来实现目标,也就是通知
 */
@Aspect
public class AnnAudience {

    private static final Logger LOGGER = LoggerFactory.getLogger(AnnAudience.class);

	// 定义切点
    @Pointcut("execution(* com.xiaokunliu.study.springinaction.aop.annotation.AnnPerformance.perform(..))")
    public void perform(){
        // 方法内容并不重要,只是作为注解的附体
    }

	// 定义通知方法
    @Before("perform()")
    public void silenceCellPhones(){
        System.out.println("silencing cell phones ... ");
    }

    @After("perform()")
    public void takeSeats(){
        System.out.println("taking seats ...");
    }

    @AfterReturning("perform()")
    public void applause(){
        System.out.println("applause ...");
    }

    @AfterThrowing("perform()")
    public void demandRefund(){
        System.out.println("demand refund ...");
    }

    @Around("perform()")
    public void watchPerformance(ProceedingJoinPoint proceedingJoinPoint){
        try{
            LOGGER.info("silencing cell phones ....");
            LOGGER.info("taking seats ....");
            proceedingJoinPoint.proceed();
            LOGGER.info("demand refund ..... ");
        }catch (Throwable e){
            LOGGER.error("catching error from watchPerformance,messages=%s", e.getMessage());
            //demandRefund();
        }
    }
  • 定义配置
// AnnConcertConfig.java
@Configuration
@EnableAspectJAutoProxy    // 启动AspectJ自动代理
@ComponentScan(basePackages = {"com.xiaokunliu.study.springinaction.aop.annotation"})
public class AnnConcertConfig {

    @Bean
    public AnnAudience audience(){
        return new AnnAudience();
    }
}
  • 编写单元测试
// TestAnnAop.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AnnConcertConfig.class)
public class TestAnnAop {

    @Autowired
    private AnnPerformance annPerformance;

    @Test
    public void testAnnAop(){
        System.out.println(annPerformance.getClass());
        // 运行结果: class com.sun.proxy.$Proxy26
    }
}
  • AOP 注解注入参数定义切面
// 定义另一个切面来处理方法调用的统计
@Aspect
public class AopTrackCounter {

    /**
     * 处理通知中的参数
     * 目标: 需要记录每个磁道被播放的次数,此时需要将记录被播放的次数与播放本身分离出来
     */
    private Map<String, Integer> trackedCounters = new ConcurrentHashMap<>();

    @Pointcut("execution(* com.xiaokunliu.study.springinaction.aop.annotation.AopCompactDisc.play(java.lang.String)) && args(trackedNumber)")
    public void trackedPlay(String trackedNumber){}

    @Before("trackedPlay(trackedNumber)")
    public void countTracked(String trackerNumberKey){
        int counter = getCountTrack(trackerNumberKey);
        trackedCounters.put(trackerNumberKey, counter + 1);
    }
	
	// 获取根据trackerNumberKey统计数据
	// 每一个方法对应一个key
    public int getCountTrack(String trackerNumberKey){
        // 1.8 版本 Map.getOrDefault
        return trackedCounters.getOrDefault(trackerNumberKey, 0);
    }
}
  • AOP注解注入参数定义连接点
// AopCompactDisc.java
public interface AopCompactDisc {
    void play(String trackedNumber);
}

// AopBlankDisc.java
public class AopBlankDisc implements AopCompactDisc {
	 @Override
    public void play(String trackNumberKey) {
        System.out.println(trackNumberKey + " AOP AopBlankDisc play .... ");
    }
}
  • 注入参数单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AnnConcertConfig.class)
public class TestAspectAop {

    @Autowired
    private AopCompactDisc aopCompactDisc;

    @Autowired
    private AopTrackCounter trackCounter;

    @Test
    public void testTrackCounter(){
        System.out.println(aopCompactDisc.getClass());
        String trackNumber = "com.xiaokunliu.study.springinaction.aop.TestAspectAop.testTrackCounter";
        aopCompactDisc.play(trackNumber);   // 3
        System.out.println(trackCounter.getCountTrack(trackNumber)); //4
		
		// 重复3,4代码
		// ....
    }
}	
  • 运行结果
    在这里插入图片描述
  • AOP 注解引入,即切面能够为现有的对象或者类增加新的方法
// 比如现在需要为现有的类或者对象增加监控的方法
// 定义一个监控的接口以及对应的实现类处理监控 -- 注意只是处理监控相关的,和Performance没有关系
public interface AnnMonitor {

    // 将这个接口的调用应用到Performance实现中
    void performMonitor();
}

public class AnnDefaultMonitor implements AnnMonitor {

    @Override
    public void performMonitor() {
        // 处理监控的方法
        System.out.println("AnnDefaultMonitor performMonitor ... ");
    }
}
  • 定义监控的切面
@Aspect
public class AnnMonitorAspect {
    @DeclareParents(value = "com.xiaokunliu.study.springinaction.aop.annotation.AnnPerformance+", defaultImpl = AnnDefaultMonitor.class)
    private static AnnMonitor monitor;
}
  • 单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AnnConcertConfig.class)
public class TestAnnAop {

    @Autowired
    private AnnPerformance annPerformance;

    @Autowired
    private AnnMonitor monitor;

    @Test
    public void testAnnAop(){
        System.out.println(annPerformance.getClass());
        System.out.println(monitor.getClass());
        System.out.println(monitor.getClass() == annPerformance.getClass());
    }
}
  • 运行结果
    在这里插入图片描述
  • AOP引入可以用下图表示(引入Spring实战的图片)
    在这里插入图片描述

AOP 基于xml声明式

// java 代码省略,基本与上述一致,这里仅做xml相关的配置
// bean_aop.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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-4.0.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">


    <!--AOP 基于Xml配置, 自动扫描指定的包目录下的java -->
    <context:component-scan base-package="com.xiaokunliu.study.springinaction.aop.xml"/>

    <!-- 声明面向切面,与注解@EnableAspectJAutoProxy对应,启动AspectJ自动代理 -->
    <aop:aspectj-autoproxy />

     <!--
        声明需要的bean
     -->
    <bean id="aopPerformance" class="com.xiaokunliu.study.springinaction.aop.xml.AopPerformanceImpl"/>

    <!--声明切面为一个bean-->
    <bean id="audience" class="com.xiaokunliu.study.springinaction.aop.xml.AopAudience"/>


    <!--
        定义spring配置的切面
    -->
    <aop:config>
        <!-- 切面 -->
        <aop:aspect ref="audience">
            <!--  切点 -->
            <aop:pointcut id="performance" expression="execution(* com.xiaokunliu.study.springinaction.aop.xml.AopPerformance.perform(..))"/>
            <!-- 通知方法 -->
            <aop:before method="silenceCellPhones" pointcut-ref="performance"/>
            <aop:after method="takeSeats" pointcut-ref="performance"/>
            <aop:after-returning method="applause" pointcut-ref="performance"/>
            <aop:after-throwing method="demandRefund" pointcut-ref="performance"/>

            <!-- 声明环绕通知 -->
            <aop:around method="watchPerformance" pointcut-ref="performance"/>
        </aop:aspect>
    </aop:config>

    <!--
        AOP 传递通知参数
    -->
    <!-- 定义切面bean -->
    <bean id="aopBlankDisc" class="com.xiaokunliu.study.springinaction.aop.xml.AopBlankDisc"/>

    <bean id="tracker" class="com.xiaokunliu.study.springinaction.aop.xml.AopTrackCounter"/>

    <!--
           注意参数名称要方法名称对应上去
    -->
    <aop:config>
        <aop:aspect ref="tracker">
            <aop:pointcut id="tracker_performance"
                          expression="execution(* com.xiaokunliu.study.springinaction.aop.xml.AopCompactDisc.play(java.lang.String)) and args(trackedNumber)"/>
            <aop:before method="trackedPlay" pointcut-ref="tracker_performance" arg-names="trackedNumber"/>
        </aop:aspect>
    </aop:config>

    <!--
        AOP 引入新的功能
    -->
    <aop:config>
        <aop:aspect>
            <aop:declare-parents types-matching="com.xiaokunliu.study.springinaction.aop.xml.AopPerformance+"
                                 implement-interface="com.xiaokunliu.study.springinaction.aop.xml.AopMonitor"
                                 default-impl="com.xiaokunliu.study.springinaction.aop.xml.AopDefaultMonitor"/>
        </aop:aspect>
    </aop:config>
</beans>
  • 基于SpringBoot定义配置
@Configuration
@ImportResource(value = "classpath:spring/beans_aop.xml")
public class AopConfig {
}
  • 单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AopConfig.class)
public class TestAspectXml {

    @Autowired
    private AopPerformance annPerformance;

    @Autowired
    private AopMonitor monitor;

    @Autowired
    private AopCompactDisc aopCompactDisc;

    @Autowired
    private AopTrackCounter trackCounter;

    @Test
    public void testAnnAop(){
    	// 运行结果如下:
    	//  class com.sun.proxy.$Proxy20
		//  class com.sun.proxy.$Proxy20
		// true
      	System.out.println(annPerformance.getClass());
        System.out.println(monitor.getClass());
        System.out.println(monitor.getClass() == annPerformance.getClass());
    }

    @Test
    public void testTrackCounter(){
    	// 执行结果如下:
    	/**
    	*	class com.sun.proxy.$Proxy21
			trackingNumber AOP AopBlankDisc play .... 
			1
			trackingNumber AOP AopBlankDisc play .... 
			2
			trackingNumber AOP AopBlankDisc play .... 
			3
			trackingNumber AOP AopBlankDisc play .... 
			4
			trackingNumber AOP AopBlankDisc play .... 
			5
			trackingNumber AOP AopBlankDisc play .... 
			6
			trackingNumber AOP AopBlankDisc play .... 
			7
			trackingNumber AOP AopBlankDisc play .... 
			8
    	*/
        System.out.println(aopCompactDisc.getClass());
        String trackNumber = "trackingNumber";
        aopCompactDisc.play(trackNumber);		// 2
        System.out.println(trackCounter.getCountTrack(trackNumber)); //3
		// 重复2,3代码 ... 
	}
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疾风先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值