在配置文件里配置 Bean 时, 有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean 配置相分离
Spring 提供了一个 PropertyPlaceholderConfigurer 的 BeanFactory 后置处理器, 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件中. 可以在 Bean 配置文件里使用形式为 ${var} 的变量, PropertyPlaceholderConfigurer 从属性文件里加载属性, 并使用这些属性来替换变量.
是一个支持运行时查询和操作对象图的强大的表达式语言
通过 SpEL 可以实现:
验证邮箱
^[_A-Za-z0-9-]+(\.[_A-Za-z0-9-]+)"+"*@[A-Za-z0-9]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$ 在初始化方法被调用前后, Spring 将把每个 Bean 实例分别传递给上述接口的以下两个方法:
public class MyBeanPostProcesser implements BeanPostProcessor { // 在init-method之前调用 @Override public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { System.out.println("postProcessBeforeInitialization: " + s); return o; } // 在init-method之后调用 @Override public Object postProcessAfterInitialization(Object o, String s) throws BeansException { System.out.println("postProcessAfterInitialization: " + s); return o; } } //Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理.
//Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一实例.
// 其典型应用是: 检查 Bean 属性的正确性或根据特定的标准更改 Bean 的属性.
//采用前置和后置处理之后
//首先运行构造函数
//然后给属性赋值
//然后访问前置处理函数
//然后访问init函数
//然后访问后置处理函数
//然后输出结果
//最后访问destroy函数
构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解
默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false
默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称
@Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.
@Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.
是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充.
AOP 的主要编程对象是切面(aspect), 而切面模块化横切关注点.
在应用 AOP 编程时, 仍然需要定义公共功能, 但可以明确的定义这个功能在哪里, 以什么方式应用, 并且不必修改受影响的类. 这样一来横切关注点就被模块化到特殊的对象(切面)里.
AOP 的好处:
AspectJ:Java 社区里最完整最流行的 AOP 框架.在 Spring2.0 以上版本中, 可以使用基于 AspectJ 注解或基于 XML 配置的 AOP
依赖包:
- aopalliance-1.0.jar
- aspectjrt.jar
- aspectjtools.jar
- aspectjweaver.jar
- org.aspectj.matcher.jar
@Around: 环绕通知, 围绕着方法执行
@Pointcut 将多个被限制的bean或者bean方法合并为一个集合,AspectJ通知注解可以直接调用合并切入点的方法,
如: combinePointCut
@Aspect @Order(0) public class AspectProcessor { // 合并切入点 @Pointcut("execution(* com.demo.aop.aspect.CalculatorImpl.*(..)))") public void combinePointCut(){} // 此函数在指定的bean方法执行前响应 // @Before("execution (* com.demo.aop.aspect.CalculatorImpl.*(..))") @Before("combinePointCut()") public void beforeAspectProcessor(JoinPoint joinPoint){ System.out.println("beforeAspectProcessor method name: " + joinPoint.getSignature().getName()); System.out.println("beforeAspectProcessor method args: " + Arrays.asList(joinPoint.getArgs())); } // 此函数在指定的bean方法执行后响应 // @After("execution (* com.demo.aop.aspect.CalculatorImpl.*(..))") @After("combinePointCut()") public void afterAspectProcessor(JoinPoint joinPoint){ System.out.println("afterAspectProcessor method name: " + joinPoint.getSignature().getName()); System.out.println("afterAspectProcessor method args: " + Arrays.asList(joinPoint.getArgs())); } // 此函数在指定的bean方法执行前、后响应 // @Around("combinePointCut()") // public void around(ProceedingJoinPoint pjp) throws Throwable{ // System.out.println("已经记录下操作日志@Around 方法执行前"); // pjp.proceed(); // System.out.println("已经记录下操作日志@Around 方法执行后"); // } // 如果只想在连接点返回的时候记录, 应使用返回通知代替后置通知 @AfterReturning(value = "combinePointCut()", returning = "result") public void afterReturningAspectProcessor(JoinPoint joinPoint, Object result){ System.out.println("afterReturningAspectProcessor method name: " + joinPoint.getSignature().getName()); System.out.println("afterReturningAspectProcessor method args: " + Arrays.asList(joinPoint.getArgs())); System.out.println("afterReturningAspectProcessor method result: " + result); } // 异常通知 @AfterThrowing(value = "combinePointCut()", throwing = "e") public void afterThrowingAspectProcessor(JoinPoint joinPoint, Exception e){ System.out.println("afterThrowingAspectProcessor method name: " + joinPoint.getSignature().getName()); System.out.println("afterThrowingAspectProcessor method args: " + Arrays.asList(joinPoint.getArgs())); System.out.println("afterThrowingAspectProcessor method throwing: " + e); } } <!--让aspectj @before @after注解生效-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<context:component-scan base-package="com.demo.aop.aspect"></context:component-scan>
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; /** * Created by plusplusxu on 2017/10/23. * * 动态代理模式主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法, * 在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法), * 因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象, * 具体应用的话,比如可以添加调用日志,做事务控制等。 * 动态代理是设计模式当中代理模式的一种。 */ @Repository public class CalculatorImplProxy { @Autowired private Calculator target; public Calculator getProxy(){ Calculator proxy = null; // 代理对象由哪一个加载器加载 ClassLoader loader = target.getClass().getClassLoader(); // 代理对象的内容 Class[] interfaces = new Class[]{Calculator.class}; // 当调用代理对象的方法的时候,该方法被执行 InvocationHandler h = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 代理对象方法执行前操作 System.out.println("method: " + method.getName() + " " + " args: " + Arrays.asList(args)); Object result = method.invoke(target, args); // 代理对象方法执行后操作 System.out.println("method: " + method.getName() + " " + " args: " + Arrays.asList(args) + " result: " + result); return result; } }; proxy = (Calculator)Proxy.newProxyInstance(loader, interfaces, h); return proxy; } } 作为 Spring JDBC 框架的核心, JDBC 模板的设计目的是为不同类型的 JDBC 操作提供模板方法. 每个模板方法都能控制整个过程, 并允许覆盖过程中的特定任务. 通过这种方式, 可以在尽可能保留灵活性的情况下, 将数据库存取的工作量降到最低.
该类声明了 jdbcTemplate 属性, 它可以从 IOC 容器中注入, 或者自动从数据源中创建.
package com.mysql; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; /** * Created by plusplusxu on 2017/10/25. * * 操作mysql的数据类 * * JdbcTemplate 类被设计成为线程安全的, 所以可以再 IOC 容器中声明它的单个实例, 并将这个实例注入到所有的 DAO 实例中. */ public class ProjectDao { public ProjectDao(JdbcTemplate jdbcTemplateObject) { this.jdbcTemplateObject = jdbcTemplateObject; } public ProjectDao() { } public JdbcTemplate getJdbcTemplateObject() { return jdbcTemplateObject; } public void setJdbcTemplateObject(JdbcTemplate jdbcTemplateObject) { this.jdbcTemplateObject = jdbcTemplateObject; } // spring 提供的访问数据库的工具类,需要配置javax.sql.DataSource // 本例中在applicationContext中配置的mysql数据源 private JdbcTemplate jdbcTemplateObject; // 添加一条项目记录 // tbl_devops_project为vsdo数据库的项目表(Project) public void addproject(Project project) { String sql = "INSERT INTO tbl_devops_project(name,public,language,description," + "admin, members, gitlab_id,gitlab_url,code_styles,sonar_lint_server_url) " + "VALUES(?,?,?,?,?,?,?,?,?,?)"; try { jdbcTemplateObject.update(sql, project.getName(),project.getPub(),project.getLanguage(),project.getDescription(), project.getAdmin(),project.getMembers(),project.getGitlab_id(), project.getGitlab_url(),project.getCode_styles(),project.getSonar_lint_server_url()); } catch (Exception e){ System.out.println(e); } return ; } // 根据项目名删除记录 public void delprojectbyname(String name) { String sql = "DELETE FROM tbl_devops_project WHERE name=?"; try { jdbcTemplateObject.update(sql,name); } catch (Exception e){ System.out.println(e); } return ; } // 删除所有项目 public void delallproject() { String sql = "DELETE FROM tbl_devops_project"; try { jdbcTemplateObject.update(sql); } catch (Exception e){ System.out.println(e); } return ; } // 更新某个项目 public void updproject(Project project) { String sql = "UPDATE tbl_devops_project set description=? WHERE name=?"; try { jdbcTemplateObject.update(sql,project.getDescription(), project.getName()); } catch (Exception e){ System.out.println(e); } return ; } // 获取所有项目 public List<Project> allproject() { List<Project> projects = null; String sql = "SELECT * FROM tbl_devops_project"; try { // ProjectMapper 项目表的映射类 projects = jdbcTemplateObject.query(sql, new ProjectMapper()); } catch (Exception e){ System.out.println(e); } return projects; } // 查询项目名对应的记录 public List<Project> queryprojectbyname(String name) { List<Project> projects = null; String sql = "SELECT * FROM tbl_devops_project WHERE name=?"; try { projects = jdbcTemplateObject.query(sql, new Object[]{name}, new ProjectMapper()); } catch (Exception e){ System.out.println(e); } return projects; } // 打印所有项目 public void displayall(){ List<Project> projects = allproject(); for(Project s : projects){ System.out.println(s); } } // 批量插入 public void insertBatch(final List<Project> projects){ String sql = "INSERT INTO tbl_devops_project(name,public,language,description," + "admin, members, gitlab_id,gitlab_url,code_styles,sonar_lint_server_url) " + "VALUES(?,?,?,?,?,?,?,?,?,?)"; jdbcTemplateObject.batchUpdate(sql, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { Project project = projects.get(i); ps.setString(1, project.getName()); ps.setBoolean(2, project.getPub()); ps.setString(3, project.getLanguage()); ps.setString(4, project.getDescription()); ps.setString(5, project.getAdmin()); ps.setString(6, project.getMembers()); ps.setInt(7, project.getGitlab_id()); ps.setString(8, project.getGitlab_url()); ps.setString(9, project.getCode_styles()); ps.setString(10, project.getSonar_lint_server_url()); } @Override public int getBatchSize() { return projects.size(); } }); } } package com.mysql; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.support.JdbcDaoSupport; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; /** * Created by plusplusxu on 2017/10/26. * * 继承于JdbcDaoSupport,直接封装了JdbcTemplate,写起来更方便 * * 该类声明了 jdbcTemplate 属性, 它可以从 IOC 容器中注入, 或者自动从数据源中创建. * */ public class JdbcDaoSupportImpl extends JdbcDaoSupport { // 添加一条项目记录 // tbl_devops_project为vsdo数据库的项目表(Project) public void addproject(Project project) { String sql = "INSERT INTO tbl_devops_project(name,public,language,description," + "admin, members, gitlab_id,gitlab_url,code_styles,sonar_lint_server_url) " + "VALUES(?,?,?,?,?,?,?,?,?,?)"; try { this.getJdbcTemplate().update(sql, project.getName(),project.getPub(),project.getLanguage(),project.getDescription(), project.getAdmin(),project.getMembers(),project.getGitlab_id(), project.getGitlab_url(),project.getCode_styles(),project.getSonar_lint_server_url()); } catch (Exception e){ System.out.println(e); } return ; } // 根据项目名删除记录 public void delprojectbyname(String name) { String sql = "DELETE FROM tbl_devops_project WHERE name=?"; try { this.getJdbcTemplate().update(sql,name); } catch (Exception e){ System.out.println(e); } return ; } // 删除所有项目 public void delallproject() { String sql = "DELETE FROM tbl_devops_project"; try { this.getJdbcTemplate().update(sql); } catch (Exception e){ System.out.println(e); } return ; } // 更新某个项目 public void updproject(Project project) { String sql = "UPDATE tbl_devops_project set description=? WHERE name=?"; try { this.getJdbcTemplate().update(sql,project.getDescription(), project.getName()); } catch (Exception e){ System.out.println(e); } return ; } // 获取所有项目 public List<Project> allproject() { List<Project> projects = null; String sql = "SELECT * FROM tbl_devops_project"; try { // ProjectMapper 项目表的映射类 projects = this.getJdbcTemplate().query(sql, new ProjectMapper()); } catch (Exception e){ System.out.println(e); } return projects; } // 查询项目名对应的记录 public List<Project> queryprojectbyname(String name) { List<Project> projects = null; String sql = "SELECT * FROM tbl_devops_project WHERE name=?"; try { projects = this.getJdbcTemplate().query(sql, new Object[]{name}, new ProjectMapper()); } catch (Exception e){ System.out.println(e); } return projects; } // 打印所有项目 public void displayall(){ List<Project> projects = allproject(); for(Project s : projects){ System.out.println(s); } } // 批量插入 public void insertBatch(final List<Project> projects){ String sql = "INSERT INTO tbl_devops_project(name,public,language,description," + "admin, members, gitlab_id,gitlab_url,code_styles,sonar_lint_server_url) " + "VALUES(?,?,?,?,?,?,?,?,?,?)"; this.getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { Project project = projects.get(i); ps.setString(1, project.getName()); ps.setBoolean(2, project.getPub()); ps.setString(3, project.getLanguage()); ps.setString(4, project.getDescription()); ps.setString(5, project.getAdmin()); ps.setString(6, project.getMembers()); ps.setInt(7, project.getGitlab_id()); ps.setString(8, project.getGitlab_url()); ps.setString(9, project.getCode_styles()); ps.setString(10, project.getSonar_lint_server_url()); } @Override public int getBatchSize() { return projects.size(); } }); } } <?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.xsd"> <!--利用spring原生的DriverManagerDataSource和mysql驱动配置数据源--> <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <!--注意一下&characterEncoding要修改为&characterEncoding--> <!--vsdo为mysql数据库名称--> <property name="url" value="jdbc:mysql://localhost:3306/vsdo?useUnicode=true&characterEncoding=utf-8"/> <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> <bean id="projectDaoImp" class="com.mysql.ProjectDao"> <!--添加jdbc访问类依赖--> <property name="jdbcTemplateObject" ref="jdbcTemplate"></property> </bean> <bean id="jdbcDaoSupportImpl" class="com.mysql.JdbcDaoSupportImpl"> <property name="dataSource" ref="datasource"></property> </bean> </beans> 事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的完整性和一致性.
事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用
事务的四个关键属性(ACID)
Spring 既支持编程式事务管理, 也支持声明式的事务管理.
Spring 还允许简单地用 @Transactional 注解来标注事务方法.
为了将方法定义为支持事务处理的, 可以为方法添加 @Transactional 注解. 根据 Spring AOP 基于代理机制, 只能标注公有方法.
![Spring[02.基础知识整理(下)]](https://cache.yisu.com/upload/information/20200312/76/259109.jpg)
当事务方法被另一个事务方法调用时, 必须指定事务应该如何传播. 例如: 方法可能继续在现有事务中运行, 也可能开启一个新事务, 并在自己的事务中运行.
![Spring[02.基础知识整理(下)]](https://cache.yisu.com/upload/information/20200312/76/259110.jpg)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。