Spring 是轻量级的开源的 JavaEE 框架 。
Spring有两个核心部分IOC 和 Aop
- IOC(Inversion of Control):控制反转,把创建对象过程交给 Spring 进行管理
- Aop(Aspect Oriented Programming):面向切面编程,不修改源代码进行功能增强
- 方便解耦,简化开发
- Aop 编程支持
- 方便程序测试
- 方便和其他框架进行整合
- 方便进行事务操作
- 降低 API 开发难度
底层原理AOP的底层使用动态代理 。动态代理有两种情况,一种为有接口的情况(使用JDK动态代理),一种为没有接口的情况(使用CGLIB动态代理)下面介绍的是有接口的情况
使用JDK动态代理:
关键方法
newProxyInstance(ClassLoader loader, class<?>[] interfaces, InvocationHandler h)该方法返回指定接口的代理实例 。
loader:用户定义代理类的类加载器;interfaces :要实现的代理类的接口列表;h:实现InvocationHandler的类,在重写的invoke方法中加入自己增强的代码部分 。使用Proxy类创建UserDao接口代理对象的代码如下,UserDao为自己定义的一个接口,接口中有一个add方法,UserDaoImpl为接口实现类,
public class JDKProxy {public static void main(String[] args) {Class[] interfaces = {UserDao.class};UserDaoImpl userDaoImpl = new UserDaoImpl();//创建接口实现类代理对象UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDaoImpl));//测试dao.add(1, 2);}}//创建代理对象class UserDaoProxy implements InvocationHandler{private Object object;//有参构造器传递对象public UserDaoProxy(Object object){this.object = object;}//写增强的逻辑,在与其关联的代理实例上调用方法时,invoke方法就会被调用@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//原方法之前执行代码System.out.println("原方法之前执行..."+"执行的方法为:"+ method.getName()+"...传递的参数为:"+ Arrays.toString(args));//原方法Object res = method.invoke(object, args);//原方法之后执行代码System.out.println("原方法之后执行...");return res;}}运行结果如下:
文章插图
自己的白话总结:创建
InvocationHandler接口的实现类并重写invoke方法,在invoke方法中添加自己的代码增强部分 。调用newProxyInstance返回代理实例并向上转型为接口,当我们调用接口中的方法时,就调用了invoke方法,从而实现了代码的功能增强 。如有错误请指正 。AOP操作实现Spring 框架一般都是基于 AspectJ 实现 AOP 操作,AspectJ 不是 Spring 组成部分,它是独立的 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用,进行 AOP 操作 。
基于 AspectJ 实现 AOP 操作有两种方式:
- 基于xml配置文件实现
- 基于注解方式实现(常用)
- 连接点:可以被增强的方法
- 切入点:被增强的方法
- 通知:实际增强的逻辑部分(说人话:自己要添加的代码)
通知的类型:
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
- 切面:把通知应用到切入点的过程(说人话:把增强的代码应用到原方法中)
切入点表达式的作用:知道对哪个类里面的哪个方法进行增强
语法结构:
execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )相关示例如下:
举例 1:对 com.hnust.spring5.dao.BookDao 类里面的 add 进行增强
execution(* com.hnust.spring5.dao.BookDao.add(..))举例 2:对 com.hnust.spring5.dao.BookDao 类里面的所有的方法进行增强
execution(* com.hnust.spring5.dao.BookDao.* (..))举例 3:对 com.hnust.spring5.dao 包里面所有类,类里面所有方法进行增强
execution(* com.hnust.spring5.dao.*.* (..))基于注解方式实现AOP导入相关jar包,以下作为参考
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.1.jar
druid-1.1.9.jar
spring-aop-5.2.6.RELEASE.jar
spring-aspects-5.2.6.RELEASE.jar
spring-beans-5.2.6.RELEASE.jar
spring-context-5.2.6.RELEASE.jar
spring-core-5.2.6.RELEASE.jar
spring-expression-5.2.6.RELEASE.jar
创建普通类
@Component//该注解实现bean注入public class User {public void add(){System.out.println("add....");}}创建增强类,这里展示前置通知,最终通知,后置通知,异常通知和环绕通知@Component@Aspect //生成代理对象public class UserProxy {//前置通知@Before(value = "https://tazarkount.com/read/execution(* com.hnust.spring5.aopanno.User.add(..))")public void before(){System.out.println("before....");}//最终通知@After(value = "https://tazarkount.com/read/execution(* com.hnust.spring5.aopanno.User.add(..))")public void after(){System.out.println("after...");}//后置通知(返回通知)@AfterReturning(value = "https://tazarkount.com/read/execution(* com.hnust.spring5.aopanno.User.add(..))")public void afterReturning(){System.out.println("afterReturning...");}//异常通知@AfterThrowing(value = "https://tazarkount.com/read/execution(* com.hnust.spring5.aopanno.User.add(..))")public void afterThrowing(){System.out.println("afterThrowing...");}//环绕通知@Around(value = "https://tazarkount.com/read/execution(* com.hnust.spring5.aopanno.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint){System.out.println("环绕之前");//执行原方法try {proceedingJoinPoint.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println("环绕之后");}}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:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启注解扫描--><context:component-scan base-package="com.hnust.spring5"></context:component-scan><!--开启Aspectj生成代理对象--><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>创建测试类@Testpublic void testAopAnno(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");User user = context.getBean("user", User.class);user.add();}执行结果:
文章插图
前置通知,在方法执行之前执行;
最终通知,在方法执行之后执行;
后置通知(返回通知),在方法返回结果之后执行;
异常通知,在方法抛出异常之后执行;
环绕通知,围绕着方法执行 。
关于最终通知和后置通知可能会有概念上的区别,以自己学的实际为准 。
如果有多个增强类对同一个方法进行增强,可以通过添加注解
@Order(数字)来设置优先级,数字越小,优先级越高 。操作数据库Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作
首先引入相关jar包,具体版本根据自己的实际版本为准,以下为参考
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.1.jar
druid-1.1.9.jar
mysql-connector-java-5.1.7-bin.jar
spring-aop-5.2.6.RELEASE.jar
spring-aspects-5.2.6.RELEASE.jar
spring-beans-5.2.6.RELEASE.jar
spring-context-5.2.6.RELEASE.jar
spring-core-5.2.6.RELEASE.jar
spring-expression-5.2.6.RELEASE.jar
spring-jdbc-5.2.6.RELEASE.jar
spring-orm-5.2.6.RELEASE.jar
spring-tx-5.2.6.RELEASE.jar
配置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:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启组件扫描--><context:component-scan base-package="com.hnust.spring5"></context:component-scan><!--配置数据库连接池 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="url" value="https://tazarkount.com/read/jdbc:mysql:///user_db" /><property name="username" value="https://tazarkount.com/read/root" /><property name="password" value="https://tazarkount.com/read/root" /><property name="driverClassName" value="https://tazarkount.com/read/com.mysql.jdbc.Driver" /></bean><!--JdbcTemplate对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--注入dataSource--><property name="dataSource" ref="dataSource"></property></bean></beans>编写dao层代码,以下示例只展示了dao层的部分实现类,其他的功能大同小异 。都学到这里了,service层肯定都会写,我就不再贴出来了 。@Servicepublic class BookDaoImpl implements BookDao{//注入JdbcTemplate@Autowiredprivate JdbcTemplate jdbcTemplate; //添加@Overridepublic void add(Book book) {String sql = "insert into t_book values(?, ?, ?)";Object[] args = {book.getUser_id(), book.getUsername(), book.getUstatus()};int update = jdbcTemplate.update(sql, args);System.out.println(update);} //修改@Overridepublic void updateBook(Book book) {String sql = "update t_book set username=?, ustatus=? where user_id=?";Object[] args = {book.getUsername(), book.getUstatus(), book.getUser_id()};int update = jdbcTemplate.update(sql, args);System.out.println(update);} //删除@Overridepublic void deleteBook(Integer id) {String sql = "delete from t_book where user_id=?";int update = jdbcTemplate.update(sql, id);System.out.println(update);}//查询@Overridepublic Book findOne(Integer id) {String sql = "select * from t_book where user_id=?";return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class),id);}}测试【springapplication.run方法 Spring-AOP学习笔记】
public class TestBook {@Testpublic void testJdbcTemplate(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookServiceImpl bookServiceImpl = context.getBean("bookServiceImpl", BookServiceImpl.class);//添加//bookServiceImpl.addBook(new Book(1,"java", "on"){});//修改//bookServiceImpl.updateBook(new Book(1,"c++","off"));//删除//bookServiceImpl.deleteBook(1);//查询//System.out.println(bookServiceImpl.findOne(1));}}
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
