Spring 从零开始-05

终于能到Spring的AOP编程了,AOP的概念特别的多,所以需要你在开始之前有点了解,然后通过代码慢慢学习!

— 切面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现。

— 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

— 通知(Advice):在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。

— 切入点(Pointcut):指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点,例如,使用正则表达式。

— 引入(Introduction):添加方法或字段到被通知的类。Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。

— 目标对象(Target Object):包含连接点的对象,也被称作被通知或被代理对象。

— AOP代理(AOP Proxy):AOP框架创建的对象,包含通知。在Spring中,AOP代理可以是JDK动态代理或CGLIB代理。

— 织入(Weaving):组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

头很晕是不是,没关系,先记住,然后说说为什么使用AOP编程,AOP-Aspect Oriented Programming面向切面编程,既然是编程,那么就说明Spring只是AOP的一种实现方式。举个例子,比如你买了房子是不是每个月都要交电费,那你是不是这样实现

public class House{
    基础方法();
    交电费();
    交水费();
    防小偷();
    ...
}

这样买个房子的代码居然需要关心很多其他方法,而且基本上与你正常的业务无关,如果哪天又增加了其他的功能,是不是又要改代码。所以我们希望将多余的方法拿出,在需要的时候再织入。Spring就给我们提供了这样的功能。

Spring对AOP的支持可以使用xml编写、使用注解还有AspectJ(当然还有经典的使用代理,这种方法比较复杂所以就不说了)。

先说xml

public class Check {
    public void CheckSecurity(){
        System.out.println("----checkSecurity----");
    }
}

上面的代码就是我们需要织入的代码

public interface TestInter {
    public void show();
    public void hh();
}
public class TestService implements TestInter{

    private String name;

    @Override
    public void show() {
        // TODO Auto-generated method stub
        System.out.println(name);
    }

    public String getName() {
        return name;
    }

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

    @Override
    public void hh() {
        // TODO Auto-generated method stub

    }

}
public class app1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ApplicationContext ac =  new ClassPathXmlApplicationContext("com/aop/aop.xml");
        TestInter testservice = (TestInter) ac.getBean("testsetvice1");
        testservice.show();
    }

}
<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 id="testsetvice1" class="com.aop.TestService" >
        <property name="name">
            <value>spirit</value>
        </property>
    </bean>

    <bean id="check" class="com.aop.Check"/>

<aop:config>
    <aop:aspect id="as" ref="check">
        <aop:pointcut id="beforepoint" expression="execution(* com.aop.TestService.show(..))"
        />
        <aop:before method="CheckSecurity" pointcut-ref="beforepoint" />
    </aop:aspect>
</aop:config>  

</beans>  

xml中定义需要在中完成配置,aop:aspect定义的是切面也就是我们的check,aop:pointcut定义切入点,表达式expression=”execution(* com.aop.TestService.show(..))”,注意*后面有个一空格,show()中的..表示接受任何参数,aop:before定义的是前置通知,也就是在切入点之前织入通知,还有aop:after后置通知,aop:around环绕通知,aop:after-throwing当抛出异常时插入通知和aop:after-returning返回时织入。

其中:After advice :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。ApplicationContext中在里面使用元素进行声明。

After return advice:在某连接点正常完成后执行的通知,不包括抛出异常的情况。ApplicationContext中在里面使用元素进行声明。

单独说一下环绕通知,需要加入参数ProceedingJoinPoint,并执行proceed()方法,表示环绕通知的方法运行。

public class Check {
    public void CheckSecurity(){
        System.out.println("----checkSecurity----");
    }

    public void round(ProceedingJoinPoint jointpoint){
        try {
            System.out.println("round before");
            jointpoint.proceed();
            System.out.println("round after");
        } catch (Throwable e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
<aop:config>
    <aop:aspect id="as" ref="check">
        <aop:pointcut id="beforepoint" expression="execution(* com.aop.TestService.show(..))"
        />
        <aop:before method="CheckSecurity" pointcut-ref="beforepoint" />
        <aop:around method="round" pointcut-ref="beforepoint" />
    </aop:aspect>
</aop:config>  

现在我们看到的通知都是没有参数,如果需要添加参数,以CheckSecurity为例。

public void CheckSecurity(String value){
        System.out.println("----checkSecurity----");
//      System.out.println("---check method arg "+name+"---");
    }
<aop:config>
    <aop:aspect id="as" ref="check">
        <aop:pointcut id="beforepoint" expression="execution(* com.aop.TestService.show(String)) and args(trouble)" />
        <aop:before method="CheckSecurity" arg-names="trouble" pointcut-ref="beforepoint" />
        <aop:around method="round" pointcut-ref="beforepoint" />
    </aop:aspect>
</aop:config> 
public class TestService implements TestInter{

    private String name;

    @Override
    public void show(String trouble) {
        // TODO Auto-generated method stub
        System.out.println(name);
    }

    public String getName() {
        return name;
    }

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

    @Override
    public void hh() {
        // TODO Auto-generated method stub
        System.out.println("hh");
    }

}

使用切面还能引入新的功能。

types-matching表示的是原实现类,记得加+,default-impl是接口的实现,implement-interface是新实现类接口定义

<aop:declare-parents
    types-matching="fuckAOP.UserManager+"
    implement-interface="fuckAOP.NewManager"
    default-impl="fuckAOP.NewManagerImpl" />

下面说一下注解装配

注解装配主要使用的是Aspect的语法。

@Aspect
public class check {

    @Pointcut("execution(* com.annotation.User.show(..))")
    private void showMethod(){
    }

    @Before("showMethod()")
    public void beforeShow(){
        System.out.println("before show ");
    }
    @Around("showMethod()")
    public void round(ProceedingJoinPoint jointpoint){
        try {
            System.out.println("round before");
            jointpoint.proceed();
            System.out.println("round after");
        } catch (Throwable e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

@Aspect表示注入的切面,@Pointcut注解表示切点,表达式与xml的方法一致,@Before表示前置通知还有其他如同xml的元素。括号中表示切点,切点已经由@Pointcut定义。

public class test {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("com/annotation/bean.xml");
        User user = (User) ac.getBean("user");
        user.show();
    }
}
public class User {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public void show(){
        System.out.println("name is "+this.name);
    }
}

在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">

    <aop:aspectj-autoproxy/>
    <bean id="user" class="com.annotation.User">
        <property name="name">
            <value>spirit</value>
        </property>
        <property name="age">
            <value>23</value>
        </property>
    </bean>
    <bean id="check" class="com.annotation.check"/>
 </beans>

如果注入需要参数的话

@Pointcut("execution(* com.annotation.User.show(String,String)) and args(testArg1,testArg2)")
    private void showMethod(String testArg1,String testArg2){
    }

    @Before("showMethod(testArg1,testArg2)")
    public void beforeShow(String testArg1,String testArg2){
        System.out.println("before show ");
    }

好了差不多就这样了,老规矩上代码。

http://download.csdn.net/detail/wsrspirit/8870455

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-14 11:36:42

Spring 从零开始-05的相关文章

Spring(05)IoC 依赖查找

目录 Spring(05)IoC 依赖查找 1. 依赖查找的今世前生 2. 单一类型依赖查找 3. 集合类型依赖查找 4. 层次性依赖查找 5. 延迟依赖查找 6. 安全依赖查找 7. 内建可查找的依赖 8. 依赖查找中的经典异常 9. 面试题精选 Spring(05)IoC 依赖查找 Spring 核心编程思想目录:https://www.cnblogs.com/binarylei/p/12290153.html 1. 依赖查找的今世前生 单一类型依赖查找 JNDI:javax.naming.

Spring 从零开始-01

由于学习需求,最近突然通知需要学习Spring,但是由于之前很少使用Java,所以感觉还是有点慢,花了大约两周,弄懂了基本的结构也编了点小程序.还是万事开头难啊,网上总是很难找到学习spring的指引资料,学习一个东西最主要的还是学习他的思想,还有就是一个可靠地学习建议,这东西会让你事半功倍,学习一定要依赖于书本,网上再好的资料都不如一本书,这个是本科+研究生的经验总结,spring学习可以参考<spring实战>,这本书写得很精彩,但是就是需要有点高度,如果你从零开始那将会有一些困难,我最近

Spring 随笔05 文件上传

本小节你将建立一个可以接受HTTP multi-part 文件的服务. 你将建立一个后台服务来接收文件以及前台页面来上传文件. 要利用servlet容器上传文件,你要注册一个MultipartConfigElement类,以往需要在web.xml 中配置<multipart-config>,而在这里,你要感谢SpringBoot,一切都为你自动配置好了. 1.新建一个文件上传的Controller: 应用已经包含一些 存储文件 和 从磁盘中加载文件 的类,他们在cn.tiny77.guide0

Spring 从零开始-04

接下来主要讲讲自动装配,主要有两种方式,一种是使用xml文件进行,另外一种是使用注解的方式. 先说xml的方式共有四种方式ByName.ByType.constructor.autodectect. ByName的要求是装配与该类属性名称相同ID的bean public class User { private String name; private int age; private Education edu; public Education getEdu() { return edu;

Spring 从零开始-03

这里说说bean装配集合,spring的支持的集合元素,其基本使用方式如同与Java的集合,所以如果对Java的集合不太了解的可以先找个帖子好好学习一下, 时间关系这里就不说了.~~ list的例子 public interface Instrument { void play(); } public class Guitar implements Instrument { @Override public void play() { // TODO Auto-generated method

Spring 教程05

spring-5 1. Xml <!-- \src\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&q

Spring Boot 05 —— web开发案例

Spring Boot 的一些坑 https://www.jianshu.com/p/3494c84b4be3 国际化: 1)设置首页: 方法1:在controller添加一个请求 @RequestMapping({"/","index.html"}) public String index(){ return "index.html"; } 方法2:设置配置文件  :WebMvcConfigurer  的  addViewControllers

4. 使用别的json解析框架【从零开始学Spring Boot】

转载:http://blog.csdn.net/linxingliang/article/details/51585921 此文章已经废弃,请看新版的博客的完美解决方案: 78. Spring Boot完美使用FastJson解析JSON数据[从零开始学Spring Boot] http://412887952-qq-com.iteye.com/blog/2315202

21. Spring Boot过滤器、监听器【从零开始学Spring Boot】

转载:http://blog.csdn.net/linxingliang/article/details/52069490 上一篇文章已经对定义Servlet 的方法进行了说明,过滤器(Filter)和 监听器(Listener)的注册方法和 Servlet 一样,不清楚的可以查看下上一篇文章(20): 本文将直接使用@WebFilter和@WebListener的方式,完成一个Filter 和一个 Listener:使用注解 @ServletComponentScan//这个就是扫描相应的Se