zoukankan      html  css  js  c++  java
  • 黑马-Spring(IOC&DI) AOP

    IOC(控制翻转)

    概念

           把对象的创建、初始化、销毁等工作交给spring容器来做

    案例

    环境

    步骤

    1、  写一个HelloWorld类

    2、  写一个配置文件   把hello类放到spring容器中

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
        <!-- 
            beans
                一个bean代表一个类
              所以beans就是很多个类
         -->
         <!-- 
             一个类
             id  标示符   
             class 类的全名
          -->
        <bean id="helloWorld" class="com.itheima09.spring.ioc.helloworld.HelloWorld">
        </bean>
    </beans>
    applicationContext.xml

    3、  客户端

    package com.itheima09.spring.ioc.helloworld.test;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.itheima09.spring.ioc.helloworld.HelloWorld;
    
    public class HelloWorldTest {
        @Test
        public void testHello(){
            HelloWorld helloWorld = new HelloWorld();
            helloWorld.hello();
        }
        
        @Test
        public void testHello_Spring(){
            /**
             * 1、启动spring容器
             * 2、从spring容器中把对象提取出来
             * 3、对象调用方法
             */
            //启动了spring容器了
            ApplicationContext context = 
                    new ClassPathXmlApplicationContext("applicationContext.xml");
            //从spring容器中把helloWorld对象提取出来了
            HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
            helloWorld.hello();
        }
    }
    View Code

    4、  说明:

    Spring容器的作用就是为HelloWorld这个类创建对象

    Spring容器的结构

    创建对象

    构造函数(用的最多)

    静态工厂

    关于静态工厂方法(https://www.jianshu.com/p/ceb5ec8f1174)

    实例工厂

     

    说明:

        给工厂类创建了一个对象helloWorldFactory,再利用工厂对象调用工厂方法

    别名

      

        

    对象的创建时机

    案例

     

    执行步骤为1,3,2

    helloword构造函数为什么调用3次

    以上两种情况是默认值,当spring容器启动的时候创建对象

    在bean有这样一个属性

    意义

           如果把lazy-init设置为true,则当spring容器启动的时候,检测不到任何错误,这样会存在很大的安全性隐患,所以一般情况下应该设置lazy-init为default/false。但是如果一个bean中有一个属性,该属性含有大量的数据,这个时候不希望该bean过早的停留在内存中。

    这个时候需要用到lazy-init为true。

    对象的scope

    默认情况(scope=singleton)

    在默认情况下放入到spring中的bean是单例的

           将来service层和dao层所有的类将放入到spring容器中,所以默认情况下这两个层的类的实例都是单例的,所以不能把数据声明到属性中。如果声明在属性中,将会成为共享的。

    Scope为prototype

      

    创建时机和scope的结合

    Scope为prototype,lazy-init为true

           在context.getBean时创建对象

    Scopse为prototype,lazy-init为false

           在context.getBean时创建对象,lazy-init为false失效

    当scpose为prototype时,始终在context.getBean时创建对象

    Scopse为singleton

           是默认情况

    Init和destroy

     

    说明:

    1、  init方法是由spring内部执行的

    2、  只有当spring容器关闭以后才能执行destroy方法,spring容器一般情况下是不会关闭的。只有当web容器销毁掉的时候才可能关闭掉,所以只要一个对象在spring容器中,在spring容器关闭之前,会一直保留。

    3、  如果一个bean的配置是scope为”prototype”,则spring容器不负责销毁。

    Spring容器做的事情

    总结

           创建对象

    1、  对象的创建方式

    2、  对象的创建时机

    3、  对象的创建的模式

    4、  Init和destroy

    5、  创建时机和创建模式的结合

    DI(依赖注入)

    概念

           给属性赋值

       

       

           给pid和name赋值的过程就是di

        

    Xml

    Setter方法

      

        

    说明:

    1、  spring容器实例化person和student两个对象

    2、  利用java的反射机制调用属性的setter方法赋值   property的 name属性由setter决定

    3、  在客户端利用context.getBean方法把spring容器中的一个对象获取了。

     

    说明:

    1、  启动spring容器

    2、  实例化person对象和student对象

    3、  给person中的属性赋值

    4、  调用person的init方法初始化

    5、  客户端利用context.getBean获取对象

    说明:

    1、  启动spring容器

    2、  实例化person对象

    3、  因为person对象依赖于student对象,所以在实例化person对象的时候必须实例化student对象,所以这个时候,在student对象上的lazy-init为true将失效

    说明:

    1、  启动spring容器

    2、  实例化student

    3、  在客户端执行context.getBean方法获取person对象

    4、  实例化person对象,调用person的构造函数

    5、  调用person中的setStudent方法,给person中的student赋值

    6、  执行person中的init方法

    7、  Person对象调用方法

    构造器

       

    说明:

    1、  constructor-arg代表指定的构造器函数的其中的一个参数

    2、  可以利用index,ref,value,type来指定唯一的构造器

    3、  如果一个bean的配置中没有constructor-arg属性,则必须利用默认的构造函数创建对象。

    4、  所以在写一个javabean的时候,应该提供属性的setter方法,默认的构造器,带参数的构造器

    IOC和DI的意义

    案例1

    需求

           编写一个文档管理系统,在该系统中有如下的结构:

    1、  Document:interface

    readDocument方法

    writeDocument方法

    2、  WordDocument 是Document的实现类

    readDocument

    writeDocument

    3、  ExcelDocument

    readDocument

    writerDocument

    4、  PDFDocument

    readDocument

    writeDocument

    5、  DocumentManager

    Document  document;

    readDocument()

    writeDocument()

    做法1

     

    说明:

    上述的代码是不完全的面向接口编程

    做法2

     

    说明:

          在代码端没有出现具体的类,完全的面向接口编程。

      在spring容器的配置文件中决定了documentManager中的接口的实现类是什么。而这个过程和java代码端没有关系。

     

    案例2

    需求

           把action调用service,service调用dao用spring来完成

    实现

    意义

           实现了完全的面向接口编程,在代码端没有要关系一个接口的实现类是什么。

    注解

    概念

    1、  用来解释说明

    2、  注解必须作用在类的某一个部分

    3、  注解的作用域范围(java,class,jvm)

    4、  注解解析器

    自定义的注解

    注解的使用

     

    注解解析器

         

    package com.itheima09.annotation;
    
    import java.lang.reflect.Method;
    
    import org.junit.Test;
    
    /**
     * 注解解析器
     * @author zd
     *
     */
    public class AnnotationParse {
        public static void parse(){
            Class classt = Itheima09.class;
            //在该类上存在ClassInfo注解
            if(classt.isAnnotationPresent(ClassInfo.class)){
                //从类上得到类的注解
                ClassInfo classInfo = (ClassInfo)classt.getAnnotation(ClassInfo.class);
                //输出该注解的name属性
                System.out.println(classInfo.name());
            }
            //获取该类的所有的方法
            Method[] methods = classt.getMethods();
            for(Method method:methods){
                //如果该方法上存在MethodInfo注解
                if(method.isAnnotationPresent(MethodInfo.class)){
                    //获取该方法上面的methodinfo注解
                    MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
                    //输出注解中的value属性
                    System.out.println(methodInfo.value());
                }
            }
        }
        
        @Test
        public void test(){
            AnnotationParse.parse();
        }
    }
    View Code

    Spring中的注解

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-2.5.xsd">
          <!-- 
              把person和student放入到spring容器中
           -->
          <bean id="person" class="com.itheima09.spring.di.annotation.Person"></bean>
          <bean id="student" class="com.itheima09.spring.di.annotation.Student"></bean>
          <!-- 
              启动依赖注入的注解解析器
           -->
          <context:annotation-config></context:annotation-config>
    </beans>
    applicationContext.xml
    package com.itheima09.spring.di.annotation;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class PersonTest {
        @Test
        public void testPerson(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person)context.getBean("person");
            person.say();
        }
    }
    PersonTest

    在spring的配置文件中

     

    说明:

    1、  启动spring容器

    2、  spring容器内部创建了两个对象person和student

    3、  当spring容器解析到

     

    启动依赖注入的注解解析器:

    1、  spring容器在容器中查找所有的bean(prerson,student)

    2、  看哪些bean的属性上面是否有Resource注解

    3、  如果属性上面有该注解,再次检查是否有name属性

    4、  如果没有name属性,则会把该注解标注的属性的名称获取到和spring容器中的id做匹配,如果匹配成功,则赋值,如果匹配不成功,则按照类型(注解的变量的类型 和 所有bean的class类型)进行匹配,如果匹配成功,则赋值(不推荐,类型匹配要求bean类型唯一出现,否则错误),如果匹配不成功,则报错。(赋值指的是person的private属性student的赋值,在Person类中对private属性student前面加上 Resource注解)

    5、  如果有name属性,则把name属性的值解析出来和spring容器中的id做匹配,如果匹配成功,则赋值,如果匹配不成功,则报错。

    6、  从上述的步骤可以看出注解的效率比较低,xml的效率比较高,注解书写比较简单,xml书写比较复杂。

    Spring容器的关于di的注解(spring自己的注解)

    按照类型匹配

    按照ID匹配

     

    注解只能应用与引用类型

    类扫描的注解

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-2.5.xsd">
        <!-- 
            把一个类放入到spring容器中,该类就是一个component
              在base-package指定的包及子包中扫描所有的类
         -->
          <context:component-scan base-package="com.itheima09.spring.scan.annotation">
          </context:component-scan>
    </beans>
    xml
    package com.itheima09.spring.scan.annotation;
    
    import javax.annotation.Resource;
    
    import org.springframework.stereotype.Component;
    
    @Component("person")
    public class Person {
        @Resource(name="student")
        private Student student;
        public void say(){
            this.student.say();
        }
    }    
    Person

    步骤

        

      

    说明:在指定的包及子包中扫描

     

    流程分析

    1、  启动spring容器

    2、  Spring容器解析类扫描的注解解析器,在base-package指定的包及子包中查找所有的类

    3、  查看哪些类上面是否含有@Component注解

    4、  如果该注解的value的属性的值为空,则把类名的第一个字母变成小写,作为id值,放入到spring容器中

    5、  如果该注解的value的属性的值不为空,则用value的属性的值作为id值,放入到spring容器中

    6、  再次查找在spring容器中的类的所有的属性,按照@Resource的规则给属性赋值

    说明

           使用了类扫描机制的做法,配置文件中的配置很简单了,但是效率越来越低。

    继承

    Xml的继承

          

    注解的继承

     

    Aop

    目的

          

       让PersonDao的数据库的操作和Transaction事务的操作分离。

    代理模式

    静态代理模式

    package com.itheima09.dao.proxy;
    
    public interface PersonDao {
        public void savePerson();
    }
    interface
    package com.itheima09.dao.proxy;
    
    public class PersonDaoImpl implements PersonDao{
        public void savePerson() {
            System.out.println("save person");
        }
    }
    impl
    package com.itheima09.dao.proxy;
    
    import com.itheima09.dao.Transaction;
    
    public class PersonDaoProxy implements PersonDao{
        private PersonDao personDao;
        private Transaction transaction;
        public PersonDaoProxy(PersonDao personDao,Transaction transaction){
            this.personDao = personDao;
            this.transaction = transaction;
        }
        public void savePerson() {
            /**
             * 1、开启事务
             * 2、进行save操作
             * 3、事务提交
             */
            this.transaction.beginTransaction();
            this.personDao.savePerson();
            this.transaction.commit();
        }
    }
    proxy
    package com.itheima09.dao.proxy;
    
    import org.junit.Test;
    
    import com.itheima09.dao.Transaction;
    
    public class ProxyTest {
        @Test
        public void testProxy(){
            /**
             * 创建PersonDaoImpl对象
             * 创建事务对象
             * 创建PersonDaoProxy对象
             */
            PersonDao personDao = new PersonDaoImpl();
            Transaction transaction = new Transaction();
            PersonDaoProxy personDaoProxy = new PersonDaoProxy(personDao, transaction);
            personDaoProxy.savePerson();
        }
    }
    proxytest

    动态代理模式

    Jdk动态代理

    接口

    目标类

          

    拦截器

       

       

    客户端

        

      

    问题

    1、  代理对象有多少方法,方法的名称是什么?

    因为代理对象和目标类一样,同样的实现了接口,所以接口中有多少方法,代理对象中就有多少个方法,名称和接口中的方法的名称一样。

    2、  拦截器中的invoke方法在什么时候执行的?

    当在客户端,代理对象调用方法的时候,进入到了invoke方法

    3、  拦截器中的invoke方法中的method参数在什么时候传递的值?

    当在客户端,代理对象调用方法的时候,进入到了invoke方法,这个时候,method参数就是代理对象调用的方法。

    4、  代理对象的方法体的内容是什么?

    代理对象的方法体的内容就是invoke方法体的内容

    代理对象的方法体:

    1、  开启事务

    2、  目标方法

    3、  事务的提交

    4、  代理对象的方法体就把事务和目标方法结合在一起了,这样做的目的就是为了让目标类的目标方法和事务的方法松耦合。

    流程图

    案例

         

    目标接口
    public interface SalaryManager {
        public void showSalary();
    }    
    View Code
    目标类

        

    package com.heima.dao.jdkproxy.salary;
    
    public class SalaryManagerImpl implements SalaryManager{
    
        @Override
        public void showSalary() {
            System.out.println("正在查看工资");
            
        }
    
    }
    View Code

      

    日志

       

    package com.heima.dao.jdkproxy.salary;
    
    public class Logger {
        public void logging(){
            System.out.println("logging");
        }
    }
    View Code
    安全性框架

        

    package com.heima.dao.jdkproxy.salary;
    
    public class Security {
        public void security(){
            System.out.println("security");
        }
    }
    View Code

      

    权限类
    package com.heima.dao.jdkproxy.salary;
    
    public class Privilege {
        private String access;
    
        public void setAccess(String access) {
            this.access = access;
        }
    
        public String getAccess() {
            return access;
        }
    }
    View Code

         

    拦截器
    package com.heima.dao.jdkproxy.salary;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class SalaryManagerInterceptor implements InvocationHandler{
        private Object target;
        private Logger logger;
        private Security security;
        private Privilege privilege;
        
        public SalaryManagerInterceptor(Object target, Logger logger,
                Security security, Privilege privilege) {
            
            this.target = target;
            this.logger = logger;
            this.security = security;
            this.privilege = privilege;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            this.logger.logging();
            this.security.security();
            if(this.privilege.getAccess().equals("admin")){
                method.invoke(target, args);
            }else{
                System.out.println("权限不足");
            }
            return null;
        }
    
    }
    View Code

    拦截器把这些内容全部结合在一起了。

    改进

    可以把日志、安全性框架等作为一个接口出现

    日志:

     

    在拦截器中:

     

    Cglib代理

    1、  产生的代理类是目标类的子类

    2、  是用字节码增强技术产生的代理类

    案例

     

     jdkProxy缺点,  通知和目标方法结合在一起的过程,放在拦截器中,需要程序员自己指定(耦合性高),所以引入aop,可以再xml中配置,提高松耦合

    Aop的概念

    切面

           事务、日志、安全性的框架,权限等就是切面

    通知

           切面中的方法就是通知

    切入点

    只有符合(表达式)切入点的条件,才能让通知和目标方法结合在一起

    连接点

    客户端调用的方法

    织入

    形成代理对象方法体的过程

    Aop的意义

     

    说明:

    1、  在开发的过程中,日志、权限、安全性的框架、目标方法完全是松耦合的

    2、  在形成代理对象的方法的过程中就把这几个结合在一起了

    切入点表达式

    3.1 execution
           由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且在Spring中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如下是execution表达式的语法:
    
    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
           这里问号表示当前项可以有也可以没有,其中各项的语义如下:
    
    modifiers-pattern:方法的可见性,如public,protected;
    ret-type-pattern:方法的返回值类型,如int,void等;
    declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
    name-pattern:方法名类型,如buisinessService();
    param-pattern:方法的参数类型,如java.lang.String;
    throws-pattern:方法抛出的异常类型,如java.lang.Exception;
            如下是一个使用execution表达式的例子:
    
    execution(public * com.spring.service.BusinessObject.businessService(java.lang.String,..))
           上述切点表达式将会匹配使用public修饰,返回值为任意类型,并且是com.spring.BusinessObject类中名称为businessService的方法,方法可以有多个参数,但是第一个参数必须是java.lang.String类型的方法。上述示例中我们使用了..通配符,关于通配符的类型,主要有两种:
    
    *通配符,该通配符主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。
           如下示例表示返回值为任意类型,在com.spring.service.BusinessObject类中,并且参数个数为零的方法:
    
    execution(* com.spring.service.BusinessObject.*())
           下述示例表示返回值为任意类型,在com.spring.service包中,以Business为前缀的类,并且是类中参数个数为零方法:
    
    execution(* com.spring.service.Business*.*())
    ..通配符,该通配符表示0个或多个项,主要用于declaring-type-pattern和param-pattern中,如果用于declaring-type-pattern中,则表示匹配当前包及其子包,如果用于param-pattern中,则表示匹配0个或多个参数。
           如下示例表示匹配返回值为任意类型,并且是com.spring.service包及其子包下的任意类的名称为businessService的方法,而且该方法不能有任何参数:
    
    execution(* com.spring.service..*.businessService())
           这里需要说明的是,包路径service..*.businessService()中的..应该理解为延续前面的service路径,表示到service路径为止,或者继续延续service路径,从而包括其子包路径;后面的*.businessService(),这里的*表示匹配一个单词,因为是在方法名前,因而表示匹配任意的类。
    
           如下示例是使用..表示任意个数的参数的示例,需要注意,表示参数的时候可以在括号中事先指定某些类型的参数,而其余的参数则由..进行匹配:
    
    execution(* com.spring.service.BusinessObject.businessService(java.lang.String,..))
    execution

    https://www.cnblogs.com/zhangxufeng/p/9160869.html

    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

           这里问号表示当前项可以有也可以没有,其中各项的语义如下:

    • modifiers-pattern:方法的可见性,如public,protected;
    • ret-type-pattern:方法的返回值类型,如int,void等;
    • declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
    • name-pattern:方法名类型,如buisinessService();
    • param-pattern:方法的参数类型,如java.lang.String;
    • throws-pattern:方法抛出的异常类型,如java.lang.Exception;
    • ..通配符,该通配符表示0个或多个项,主要用于declaring-type-pattern和param-pattern中,如果用于declaring-type-pattern中,则表示匹配当前包及其子包,如果用于param-pattern中,则表示匹配0个或多个参数。
      • *通配符,该通配符主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。

     

    ?表示可选可不选  可以不填

    必须写 有2个:   1  ret-type-pattern:方法的返回值类型,如int,void等;

    • name-pattern:方法名类型,如buisinessService();
    • param-pattern:方法的参数类型,如java.lang.String;

    代表所有的公共方法

     

    代表所有的以set开头的方法

     

    代表com.xyz.service包下的AccoutService类的所有的方法

     

    代表com.xyz.service包下的所有的类的所有的方法

     

    代表com.xyz.service包及子包下的所有的类的所有的方法

     

    代表com.itheima.spring.aop.xml包下的所有的类的有三个参数,第一个参数为Long,第二个参数为String,第三个参数为任意类型的所有的方法

     

    (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

    (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

    (3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

    (4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

    (5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

    Spring的aop

    步骤

    目标接口

       

    目标类

        

    切面

     

    Spring的配置文件

    执行流程

    1、  context.getBean时,如果该类没有生成代理对象,则返回对象本身

    2、  如果产生了代理对象,则返回代理对象

    如果目标类实现了接口,则采用jdkproxy生成代理对象,如果目标类没有实现接口,则采用cglibproxy生成代理对象,而生成代理对象是由spring容器内部完成的。

    通知

    前置通知

    在目标方法执行之前执行。

    后置通知

           在目标方法执行之后执行

           可以获取目标方法的返回值

           当目标方法遇到异常,不执行

    最终通知

           无论目标方法是否遇到异常都会执行,相当于代码中的finnaly

    异常通知

           获取目标方法抛出的异常

    环绕通知

           能够控制目标方法的执行

    package com.heima.spring.aop.xml.advice;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class Transaction {
        public void begeinTransaction(JoinPoint joinPoint){
            System.out.println(joinPoint.getTarget());
            System.out.println(joinPoint.getArgs());
            System.out.println(joinPoint.getSignature().getName());
            System.out.println("begin transaction");
        }
        public void commit(JoinPoint joinPoint,Object val){
            System.out.println(val);
            System.out.println("commit");
        }
        public void finalyMethod(JoinPoint joinPoint){
            
            System.out.println("finaly method");
        }
        public void throwingMethod(JoinPoint jp,Throwable ex){
            System.out.println(ex.getMessage());
            System.out.println("异常");
            
        }
        public void arroundMethod(ProceedingJoinPoint pjp)throws Throwable{
            System.out.println("环绕通知aaa");
            pjp.proceed();
            System.out.println("环绕通知bbbb");
        }
    }
    xml

    案例:异常处理

    技术图

     

    实现

    切面

    目标类

    配置

    从配置中可以看出,把service层所有的类当成目标类,只要service层所有的类的所有的方法抛出异常,则exceptionAspect中的异常通知就会获取到目标方法抛出的异常,所以在这里异常通知就是用来处理异常的,而且只有一个方法。并且该切面和所有的其他类都是松耦合的。

    案例:权限的处理

    技术图

     

    组成

    1、  写dao层和service层的类和接口

    2、  自定义的注解@PrivilegeInfo

    3、  注解解析器:解析目标方法上面的注解的name属性的值

    4、  写一个权限类Privilege(name)

    5、  写一个关于权限的判断的切面,在切面中写一个环绕通知

    实现

           参照:/day03-02-itheima09-springAOP-xml-ex-privilege

    扩展作业

    利用spring的aop的环绕通知,记录如下的信息:

     目标类     目标方法     执行时间   方法的起始时间  方法的结束时间 

    把上述的几个内容保存在数据库中,用jfreechar或者用table显示出来

    AOP注解(了解)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-2.5.xsd
               http://www.springframework.org/schema/aop 
               http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
        <context:component-scan base-package="com.itheima09.springaop.annotation.transaction"></context:component-scan>    
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>
    xml
    package com.itheima09.springaop.annotation.transaction;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    /**
     * @Aspect
     * ==
     * <aop:config>
     *         <aop:pointcut 
                expression="execution(* com.itheima09.springaop.annotation.transaction.PersonDaoImpl.*(..))" 
                id="aa()"/>
     * </aop:config>
     * @author zd
     *
     */
    @Component("transaction")
    @Aspect//说明该注解标注的类是一个切面类
    public class Transaction {
        
        @Pointcut("execution(* com.itheima09.springaop.annotation.transaction.PersonDaoImpl.*(..))")
        private void aa(){} //方法标签    修饰符最好是private 返回值必须是void
        
        @Before("aa()")
        public void beginTransaction(){
            System.out.println("begin transaction");
        }
        @AfterReturning(value="aa()",returning="ex")
        public void commit(JoinPoint joinPoint,Object ex){
            System.out.println("commit");
        }
    }
    transaction
  • 相关阅读:
    玩转----使用数据驱动ddt时,如何写测试报告2种方法
    玩转----svn--入门
    玩转----Selenium家族简介
    起名的含义
    重新开始
    学习django: 庄园漫步
    测试常用的表格
    【Kata Daily 190927】Counting sheep...(数绵羊)
    【Kata Daily 190924】Difference of Volumes of Cuboids(长方体的体积差)
    【Kata Daily 190923】Odder Than the Rest(找出奇数)
  • 原文地址:https://www.cnblogs.com/hellowq/p/9862319.html
Copyright © 2011-2022 走看看