美文网首页
spring-AOP基础,jdbctemplate基础

spring-AOP基础,jdbctemplate基础

作者: 浅时光_love | 来源:发表于2019-08-24 23:49 被阅读0次

    AOP-面向切面编程

            AOP是对OOP的有益补充,面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。

            但是在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。

            我们当然可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

            一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。

    AOP就是这样一种设计思想,常用动态代理来实现,已被广泛应用到各种框架当中,可以把它看做拦截器。

    AOP一般使用动态代理思想,java 中的Proxy或者第三方类库cglib来实现,如果不了解动态代理,请参阅:|--------传送门--------||

    Spring中的AOP

    spring中的AOP使用cglib来实现,通过实现四种不同的接口完成不同的切入。

    具体的,1.写一个Bean,该Bean中的某些public非final方法需要被切入2.写一个通用的代理类,实现对应的接口3.配置这两个bean及依赖关系,并配置主代理即class=org.springframework.aop.framework.ProxyFactoryBean。

    MethodBeforeAdvice

    该接口有一个方法 public void before(Method method, Object[] args, Object target)throws Throwable

    method表示切入方法,args表示其参数,target表示要被切入的Bean

    重写该方法表示在执行method之前会先执行before()中的代码

    AfterReturningAdvice

    有方法afterReturning(Object returnValue, Method method, Object[] args, Object target)throws Throwable

    同上,重写该方法表示在执行method之后会执行afterReturning()中的代码

    ThrowsAdvice

    有方法public void afterThrowing(IllegalArgumentException e) throws Throwable

    同上,重写该方法表示在执行method时抛出异常IllegalArgumentException会执行afterReturning()中的代码

    MethodInterceptor

    有方法public Object invoke(MethodInvocation methodInvocation)

    通过调用methodInvocation.proceed()执行原方法

    实例:

    1.写bean

    public class CustomerService {

        private String name;

        private String url;

        public void setName(String name) {

            this.name = name;

        }

        public void setUrl(String url) {

            this.url = url;

        }

        public void printName() {

            System.out.println("Customer name : " + this.name);

        }

        public void printURL() {

            System.out.println("Customer website : " + this.url);

        }

        public void printThrowException() {

            throw new IllegalArgumentException();

        }

    }

    2.写通用代理

    public class LslBeforeMethod implements MethodBeforeAdvice {

        public void before(Method arg0, Object[] args, Object target)

                throws Throwable {

            System.out.println(" Before method ");

        }

    }

    3.配置依赖关系

    <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.xsd">

        <bean id="customerService" class="CustomerService">

            <property name="name" value="S" />

            <property name="url" value="http://lsl----lsl.com" />

        </bean>

        <bean id="lslBeforeMethodBean" class="LslBeforeMethod" />

        <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

            <property name="target" ref="customerService" />

            <property name="interceptorNames">

                <list>

                    <value>lslBeforeMethodBean</value>

                </list>

            </property>

        </bean>

    </beans>

    之后每次执行CustomerService中的方法都会被LslBeforeMethod进行拦截。

    由方法名或正则匹配进行精确切入

    上述配置会使所有方法都被拦截,为了更加灵活精准切入,spring准备了多种配置方式。

    具体的1.org.springframework.aop.support.DefaultPointcutAdvisor 指默认的总代理 2.pointcut:指定切入点,advice:指定代理

    <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.xsd">

        <bean id="customerService" class=CustomerService">

            <property name="name" value="ad" />

            <property name="url" value="asd" />

        </bean>

        <bean id="lslAroundMethodBean" class="LslAroundMethod" />

        <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

            <property name="target" ref="customerService" />

            <property name="interceptorNames">

                <list>

                    <value>customerAdvisor</value>

                </list>

            </property>

        </bean>

        <bean id="customerPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">

            <property name="mappedName" value="printName" />

        </bean>

        <bean id="customerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">

            <property name="pointcut" ref="customerPointcut" />

            <property name="advice" ref="lslAroundMethodBean" />

        </bean>

    </beans>

    即总代理变成org.springframework.aop.support.DefaultPointcutAdvisor

    通过指定pointcut指定切入的方法

    通过指定advice指定执行代理

    如果要使用正则,则将pointcut变为patterns,即替换为

    <property name="patterns">

        <list>

            <value>.*URL.*</value>

        </list>

    </property>

    AspectJ

    可以通过使用注解的形式完成AOP,AspectJ是一个第三方类库,直接静态织入自动生成的代理类。

    AspectJ 支持的注解类型如下:

    @Before

    @Aspect

    @After

    @AfterReturning

    @AfterThrowing

    @Around

    使用Aspectj可添加依赖

            <dependency>

                <groupId>org.aspectj</groupId>

                <artifactId>aspectjweaver</artifactId>

                <version>1.9.2</version>

            </dependency>

            <dependency>

                <groupId>org.aspectj</groupId>

                <artifactId>aspectjtools</artifactId>

                <version>1.9.2</version>

            </dependency>

            <dependency>

                <groupId>org.aspectj</groupId>

                <artifactId>aspectjrt</artifactId>

                <version>1.9.2</version>

            </dependency>

    注意更换版本

    pom.xml中添加声明<aop:aspectj-autoproxy/>

    @Aspect用于声明一个class,表示该class是一个切面class,之后使用注解指定某个class的某个方法,进行静态织入

    1.声明普通的bean

    @Component("bean")

    public class TestMethod {

        public void before(String name) {

            System.err.println("the param Name is " + name);

        }

        public void after(String name) {

            System.err.println("the param Name is " + name);

        }

        public void around(String name) {

            System.err.println("the param Name is " + name);

        }

    }

    2.声明切面Aspect

    @Aspect

    @Component

    public class ExecutionAspect {

        @Before("execution(* club.myapp.aspectJ.*.before*(..))")

        public void doBefore(JoinPoint joinPoint) throws Throwable {

            System.err.println("这是一个前置通知,在方法调用之前被执行!!!");

        }

        @After("execution(* club.myapp.aspectJ.*.after*(..))")

        public void doAfter(JoinPoint joinPoint) throws Throwable {

            System.err.println("这是一个后置通知,在方法调用之后被执行!!!");

        }

        @Around("execution(* club.myapp.aspectJ.*.around*(..))")

        public void doAround(ProceedingJoinPoint joinPoint) throws Throwable {

            System.err.println("这是一个环绕通知,在方法调用前后都会执行!!!");

            System.err.println("执行前");

            joinPoint.proceed();

            System.err.println("执行后");

        }

    }

    对于信息"execution(* club.myapp.aspectJ.*.before*(..))"来说: 第一个*表示返回类型(*表示任意类型返回值) 紧跟着某个方法的绝对路径,可使用正则匹配。

    JdbcTemplate

    Spring中自带的一个封装JDBC加强功能的一个class。

    使用时要添加依赖:

    <name>springJdbc</name>

    <url>http://maven.apache.org</url>

      <dependency>

          <groupId>org.springframework</groupId>

          <artifactId>spring-jdbc</artifactId>

          <version>${spring.version}</version>

        </dependency>

    同时配置数据源,导入bean

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

          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

                              http://www.springframework.org/schema/context

                              http://www.springframework.org/schema/context/spring-context.xsd">

        <context:annotation-config/>

        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>

            <property name="url" value="jdbc:mysql://localhost/test?serverTimezone=UTC"/>

            <property name="username" value="root"/>

            <property name="password" value="123456"/>

        </bean>

        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

            <property name="dataSource" ref="dataSource"/>

        </bean>

    </beans>

    使用时创建JdbcTemplate实例即可

            JdbcTemplate jdbcTemplate=(JdbcTemplate) context.getBean("jdbcTemplate");

            String sql="insert into student values(?,?,?)";

            int count=jdbcTemplate.update(sql,new Object[]{2,"shiyanlou2",18});

            System.out.println(count);

    如上所示,JdbcTemplate内置多种方法执行sql,实际上就是对JDBC进行了进一步的封装

    执行查询时可传入一个DAO.class返回RowMapper<DAO>对象进行ORM映射

    RowMapper<Student> rowMapper=new BeanPropertyRowMapper<Student>(Student.class);

    List<Student> list=jdbcTemplate.query(sql,rowMapper);

    for(Student student:list){

        System.out.println(student.getId()+" "+student.getName());

    }

    相关文章

      网友评论

          本文标题:spring-AOP基础,jdbctemplate基础

          本文链接:https://www.haomeiwen.com/subject/kbmcectx.html