Spring之AOP面向切面编程和JDBC

文章目录

      • 一、动态代理Proxy:
      • spring aop
        • 通过注解方式
        • 表达式标签
        • 注解方式类型的顺序:
      • Spring-JDBC

一、动态代理Proxy:

利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象),代理的是接口(Interfaces),不是类(Class),也不是抽象类。在运行时才知道具体的实现,spring aop就是此原理。
一:写一个接口:

package com.openlab.dao;
public interface UserDao {public int add(int a,int b);
}

接着写一个类实现接口:

package com.openlab.dao.Impl;
import com.openlab.pojo.PeoPle;
import lombok.Data;
import org.springframework.stereotype.Component;
@Component
@Data
public class PeopleDao {public void save(){System.out.println("PeopleDao中的实现类1---save");}public Integer test(int a,int b){System.out.println("PeopleDao实现类执行了------加法运算");return a+b;}
}

测试类,写了一个InvocationHandler内部类
也可以写一个写一个类实现InvocationHandler接口:
我写的是第一种内部类方式:

package com.openlab;
import com.openlab.dao.Impl.UserDaoImpl;
import com.openlab.dao.UserDao;
import com.openlab.config.Springconfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class MyTest {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(Springconfig.class);final UserDaoImpl userDao = new UserDaoImpl();Class[] interfaces = userDao.getClass().getInterfaces();UserDao o = (UserDao) Proxy.newProxyInstance(MyTest.class.getClassLoader(), interfaces, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("方法执行前:"+method.getName()+"......."+ Arrays.toString(args));Object invokes = method.invoke(userDao,args);System.out.println("方法执行之后");return invokes;}});int add = o.add(3, 5);System.out.println(add);}
}

Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

第一个参数(ClassLoader loader 表示用哪个类的加载器
第二参数Class[] interfaces 动态类需要实现的接口个数
第三参数InvocationHandler h 动态代理方法在执行时,会调用h里面的invoke方法去执行
返回类型是Object类型,需要强转为我们需要的接口类型;

上面代码中,代理u对象,调用UserDao中的add方法时,自动执行InvocationHandler中的invoke方法。

测试结果:

在这里插入图片描述

spring aop

  1. 连接点:类里面那些方法可以被增强,这些方法称为连接点
  2. 切入点:实际被增强的方法
  3. 通知:实际增强的逻辑部分 类型:前置通知 后置通知 环绕通知 异常通知 最终通知
  4. 切面:动作,把通知应用到切入点过程
通过注解方式

aop注解:
Advice(通知、切面): 某个连接点所采用的处理逻辑,也就是向连接点注入的代码, AOP在特定的切入点上执行的增强处理。
@Before: 标识一个前置增强方法,相当于BeforeAdvice的功能.
@After: final增强,不管是抛出异常或者正常退出都会执行.
@AfterReturning: 后置增强,似于AfterReturningAdvice, 方法正常退出时执行.
@AfterThrowing: 异常抛出增强,相当于ThrowsAdvice.
@Around: 环绕增强,相当于MethodInterceptor.

表达式标签

表达式标签
execution():用于匹配方法执行的连接点
args(): 用于匹配当前执行的方法传入的参数为指定类型的执行方法
this(): 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
target(): 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
within(): 用于匹配指定类型内的方法执行;
@args():于匹配当前执行的方法传入的参数持有指定注解的执行;
@target():用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
@within():用于匹配所以持有指定注解类型内的方法;
@annotation:用于匹配当前执行方法持有指定注解的方法;

PeoPleDaoProxy 类

package com.openlab.dao.proxy;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect
@Component
public class PeoPleDaoProxy {@Pointcut(value="execution(* com.openlab.*.*.*(..))")//Pointcut(切入点)://  JoinPoint的集合,是程序中需要注入Advice的位置的集合,指明Advice要在什么样的条件下才能被触发,在程序中主要体现为书写切入点表达式。public void Poin(){}@Before(value = "execution(* com.openlab.dao.Impl.PeopleDao.*())")  //前置通知public void before(){System.out.println("方法执行前");}@After(value = "execution(* com.openlab.dao.Impl.PeopleDao.*())")  //后置通知public void after(){System.out.println("方法执行后");}@AfterReturning(value = "execution(* com.openlab.dao.Impl.PeopleDao.*())")public void afterReturning(){System.out.println("最终执行");}@AfterThrowing(value="Poin()")//异常通知public void aferthrow(){System.out.println("出异常了");}@Around(value = "execution(* com.openlab.dao.Impl.PeopleDao.*())")  //环绕通知public void around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("执行之前环绕");joinPoint.proceed();System.out.println("执行之后环绕");}
}

调用类:

package com.openlab.dao.Impl;import com.openlab.pojo.PeoPle;
import lombok.Data;
import org.springframework.stereotype.Component;@Component
@Data
public class PeopleDao {public void save(){System.out.println("PeopleDao中的实现类1---save");}public Integer Update(PeoPle people){System.out.println("PeopleDao实现类执行了:"+people);return 10;}public Integer test(int a,int b){System.out.println("PeopleDao实现类执行了------加法运算");try{int month=1/0;}catch(Throwable e){System.err.println("方法出错");}finally {System.out.println("方法的finally");}return a+b;}
}

applicationContext.xml 配置


<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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.openlab"/><aop:aspectj-autoproxy /> //重点beans>

测试类

package com.openlab;
import com.openlab.dao.Impl.PeopleDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ProxyTest {@Testpublic void test01(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");PeopleDao peopleDao = context.getBean(PeopleDao.class);peopleDao.save();Integer test = peopleDao.test(5, 7);System.out.println(test);}
}

测试结果:
在这里插入图片描述

注解方式类型的顺序:

环绕前通知 前置通知 (运行方法) 异常通知 最终通知 后置通知 环绕后通知

xml配置方式

所以我们只需要把aop:aspectj-autoproxy注释掉,切面类的注释方式就失效了。所以我就只修改了xml的配置:

   <context:component-scan base-package="com.openlab" >context:component-scan><bean id="PeoPleDaoProxy" class="com.openlab.dao.proxy.PeoPleDaoProxy">bean><aop:config><aop:pointcut expression="execution(* com.openlab.*.*.*(..))" id="poin"/><aop:aspect ref="PeoPleDaoProxy"><aop:before method="before" pointcut-ref="poin">aop:before><aop:after method="after" pointcut-ref="poin">aop:after><aop:after-returning method="afterReturning" pointcut-ref="poin"/><aop:after-throwing method="aferthrow"  pointcut-ref="poin"/><aop:around method="around" pointcut-ref="poin"/>aop:aspect>aop:config>

我们发现xml配置类型的顺序和注解方式顺序不一样;最后发现是xml中。

Spring-JDBC

首先:pom.xml引入依赖

<dependency><groupId>org.springframeworkgroupId><artifactId>spring-jdbcartifactId><version>5.3.5version>dependency>
<dependency><groupId>mysqlgroupId><artifactId>mysql-connector-javaartifactId><version>8.0.26version>dependency>

在准备db.properties

#\u8FDE\u63A5\u8BBE\u7F6E
//com.mysql.jdbc.Driver 是 mysql-connector-java 5中的, 
//com.mysql.cj.jdbc.Driver 是 mysql-connector-java 6后的
jdbc.driverClassName=com.mysql.cj.jdbc.Driver//我的mysql数据库是8.26的所以是com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/t1				//jdbc:mysql: 是指JDBC连接方式;localhost: 是指你的本机地址
jdbc.name=root            //用户名          
jdbc.password=root  //密码

创建数据库对应的类
在这里插入图片描述

package com.openlab.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Classes {private int id;private String mnane;private int sums;
}

dao包建接口:

package com.openlab.dao;import com.openlab.pojo.Classes;public interface ClassesDao {public int add(Classes role);//添加public int updat(Classes role);//更新public int delete(int roleid);//删除
}

Impl包里创建类实现接口:

package com.openlab.dao.Impl;import com.openlab.dao.ClassesDao;
import com.openlab.pojo.Classes;
import org.springframework.jdbc.core.JdbcTemplate;public class ClassDaoImpl implements ClassesDao {private JdbcTemplate jdbcTemplate;public JdbcTemplate getJdbcTemplate() {return jdbcTemplate;}public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}@Overridepublic int add(Classes classes) {String sql="insert into class(id,mnane,snums) value(?,?,?)";// 定义数组来存放SQL语句中的参数Object[] obj = new Object[] {classes.getId(),classes.getMnane(),classes.getSums()};// 执行添加操作,返回受SQL语句影响的条数int num = this.jdbcTemplate.update(sql, obj);return num;}@Overridepublic int updat(Classes classes) {String sql="update into class(id,mnane,snums) value(?,?,?)";// 定义数组来存放SQL语句中的参数Object[] obj = new Object[] {classes.getId(),classes.getMnane(),classes.getSums()};// 执行添加操作,返回受SQL语句影响的条数int num = this.jdbcTemplate.update(sql, obj);return num;}@Overridepublic int delete(int id) {// 定义SQLString sql = "delete from class where id=?";// 执行更新操作,返回受SQL语句影响的条数int num=this.jdbcTemplate.update(sql,id);return num;}
}

xml配置


<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 https://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder location="classpath:db.properties">context:property-placeholder><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="driverClassName" value="${jdbc.driverClassName}">property><property name="url" value="${jdbc.url}">property><property name="username" value="${jdbc.name}">property><property name="password" value="${jdbc.password}">property>bean><bean id="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource">property>bean><bean id="classImpl" class="com.openlab.dao.Impl.ClassDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate">property>bean>
beans>

测试类:

package com.openlab;import com.openlab.dao.Impl.ClassDaoImpl;
import com.openlab.pojo.Classes;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Testclass {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans2.xml");ClassDaoImpl classimpl = context.getBean("classImpl", ClassDaoImpl.class);Classes lala = new Classes(10, "拉拉", 38);int adds = classimpl.add(lala);if(adds>0) {System.out.println("成功插入"+adds+"条数据!");}else {System.out.println("插入操作执行失败");}}
}

插入结果:
在这里插入图片描述
在这里插入图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部