zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Java安全之JNDI注入
    Visual Studio 2019 升级16.8之后(升级.Net 5),RazorTagHelper任务意外失败
    .Net Core 3.1升级 .Net 5后出现代码错误 rzc generate exited with code 1.
    重走py 之路 ——普通操作与函数(三)
    重走py 之路 ——字典和集合(二)
    设计模式结(完结篇)
    重走py 之路 ——列表(一)
    RestfulApi 学习笔记——分页和排序(五)
    RestfulApi 学习笔记——查询与过滤还有搜索(五)
    Android开发 Error:The number of method references in a .dex file cannot exceed 64K.Android开发 Error:The number of method references in a .dex file cannot exceed 64K
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5159928.html
Copyright © 2011-2022 走看看