中国空间站设计在轨飞行多少年,微山网站建设公司,珠海网站建设工程,海阔淘宝客助手wordpress演示站 | 紫色清新商城模板文章目录一 简介二 IOC1 底层原理2 实现过程3 Spring 实现 IOC 的两个接口二 Bean1 普通 Bean 与 FactoryBean2 Bean 单例与否的设置3 Bean 的生命周期三 IOC 的 Bean 管理#xff08;XML#xff09;1 创建对象2 属性注入 - 使用 set 方法3 属性注入 - 通过有参构造器实现3 注…
文章目录一 简介二 IOC1 底层原理2 实现过程3 Spring 实现 IOC 的两个接口二 Bean1 普通 Bean 与 FactoryBean2 Bean 单例与否的设置3 Bean 的生命周期三 IOC 的 Bean 管理XML1 创建对象2 属性注入 - 使用 set 方法3 属性注入 - 通过有参构造器实现3 注入属性为 null / 包含特殊符号4 注入外部 Bean5 注入内部 Bean6 注入 array / list / map / set7 自动装配8 使用外部文件配置 Bean四 IOC 的 Bean 管理注解1 Spring 针对创建 Bean 对象提供的注解2 创建对象的步骤3 属性注入 - Autowared4 属性注入 - Qualifier5 属性注入 - Resource6 属性注入 - Value7 完全注解开发五 AOP 概述1 动态代理的两种情况2 JDK 动态代理实例六 AspectJ 的使用注解1 切入点表达式2 使用流程3 相同切入点的抽取4 完全注解开发七 JdbcTemplate1 配置2 添加 / 修改 / 删除 操作3 查询值4 查询单个对象5 查询多个对象八 Spring 事务管理1 注解声明式事务管理的步骤2 Transactional 的参数配置3 完全注解的 声明式事务管理一 简介
Spring 是轻量级的开源的 JavaEE 框架Spring 有两个核心部分IOCInversion of Control控制反转 和 AOPAspect Oriented Programming面向切面编程IOC 是一种设计思想核心是将设计好的对象交给容器控制而不是传统的在对象内部直接控制。 把创建和查找依赖对象的控制权交给了容器由容器进行注入组合对象所以对象与对象之间是松散的耦合。AOP 是针对业务处理过程中的切面进行提取它所面对的是处理过程中的某个步骤或阶段以获得逻辑过程中各部分之间低耦合性的隔离效果。简言之AOP 可以做到不修改源代码进行功能增强。OOP 面向名词领域AOP 面向动词领域。 二 IOC
1 底层原理
xml 解析工厂模式反射
2 实现过程
配置 xml 文件的 bean 标签使用 id 属性标注对象名使用 class 属性标注类所在的位置在 bean 标签内部使用 property 标签绑定依赖关系
bean idstudentDAO classdao.StudentInfoDAOproperty name... value...
/bean使用工厂类利用反射机制创建对象
class MyFactory {public DAO getDAO () {String classValue // 经过一些方法得到dao.StudentInfoDAO; // 解析xml获取bean标签的class属性值Class clazz Class.forName(classValue); // 获取指定类的 Class 对象return (StudentInfoDAO)clazz.newInstance(); // 根据 Class 对象创建实例}
} 经过上述过程各类间进一步解耦。例如此时 xml 配置中class 属性变动不会对其创建造成影响。
3 Spring 实现 IOC 的两个接口
BeanFactorySpring 内部的使用接口不提供给开发人员进行使用。加载配置文件时候不会创建对象在获取对象使用才去创建对象ApplicationContextBeanFactory 接口的子接口功能更强大加载配置文件时候就会把在配置文件对象进行创建。 把创建资源的过程放在服务器启动时。有两个实现类FileSystemXmlApplicationContext 传入 xml 文件的绝对路径和 ClassPathXmlApplicationContext 传入 xml 文件的相对路径以 src 作为起始目录 二 Bean
1 普通 Bean 与 FactoryBean
普通 Bean 的定义类型和返回类型相同而 FactoryBean 的定义类型和返回类型可以不同要创建 FactoryBean需要实现接口 FactoryBeanT
bean idmyBean classcom.atguigu.spring5.factorybean.MyBean/beanpublic class MyBean implements FactoryBeanCourse { // 返回类型是CourseOverridepublic Course getObject() throws Exception {Course course new Course();course.setCname(abc);return course;}Overridepublic Class? getObjectType() {return null;}Overridepublic boolean isSingleton() {return false;}
}2 Bean 单例与否的设置
默认 Bean 是单例对象通过 Bean 标签的 scopesingleton / prototype 选择单例与否设置 scope singleton 加载 spring 配置文件时候就会创建单实例对象设置 scope prototype 在调用 getBean 方法时候创建多实例对象
3 Bean 的生命周期
1通过构造器创建 bean 实例无参构造 2为 bean 的属性设置值和对其他 bean 引用调用 set 方法 3把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization可选 4调用 bean 的初始化的方法需要配置初始化的方法 5把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization可选 6bean 可以使用获取到了对象 7当容器关闭时候调用 bean 的销毁的方法需要配置销毁的方法
后置处理器在配置后会对所有的 Bean 生效
不含后置处理器的 Bean 生命周期演示
public class Orders {private String oname;// 无参构造public Orders() {System.out.println(第一步 执行无参构造创建 bean 实例);}public void setOname(String oname) {this.oname oname;System.out.println(第二步 调用 set 方法设置属性值);}// 初始化的方法public void initMethod() {System.out.println(第三步 执行初始化的方法);}// 销毁的方法public void destroyMethod() {System.out.println(第五步 执行销毁的方法);}
}三 IOC 的 Bean 管理XML
Bean 管理包含两个步骤创建对象、注入属性
1 创建对象
创建对象时候默认是执行无参数构造方法完成对象创建。
bean idcustom_instance_name classpojo.MyClass/bean
id唯一标识相当于对象名class类全路径
2 属性注入 - 使用 set 方法
在 Bean 中实现要注入属性的 set 方法
public class Book {//创建属性private String bname;private String bauthor;//创建属性对应的 set 方法public void setBname(String bname) {this.bname bname;}public void setBauthor(String bauthor) {this.bauthor bauthor;}
}在 xml 文件中配置要注入的属性名以及属性值
bean idbook classcom.atguigu.spring5.Book!--name类里面属性名称 value向属性注入的值--property namebname value易筋经/propertyproperty namebauthor value达摩老祖/property
/bean3 属性注入 - 通过有参构造器实现
创建类定义属性创建有参构造器
public class Orders {//属性private String oname;private String address;//有参构造public Orders(String oname,String address) {this.oname oname;this.address address;}在 xml 文件中配置constructor-arg 指定了调用有参数的构造器
bean idorders classcom.atguigu.spring5.Orders!--constructor-arg 指定了调用有参数的构造器--!--也可以使用index属性代替name属性--constructor-arg nameoname value电脑/constructor-argconstructor-arg nameaddress valueChina/constructor-arg
/bean3 注入属性为 null / 包含特殊符号
bean idbook classcom.atguigu.spring5.Bookproperty nameaddressnull//propertyproperty nametelvalue![CDATA[...]]/value/property
/bean4 注入外部 Bean
示例使用 set 方法进行注入要求 userService 实现了其 dao 属性的 set 方法name 是类里面属性名称ref 是创建 userDao 对象 bean 标签 id 值
bean iduserService classcom.atguigu.spring5.service.UserService!--注入 userDao 对象name 属性类里面属性名称ref 属性创建 userDao 对象 bean 标签 id 值--property nameuserDao refuserDaoImpl/property
/beanbean iduserDaoImpl classcom.atguigu.spring5.dao.UserDaoImpl/bean5 注入内部 Bean
示例使用 set 方法进行注入如果注入的类型是 Bean则将 value 标签替换为 ref 标签
!--内部 bean--
bean idemp classcom.atguigu.spring5.bean.Emp!--设置对象类型属性--property namedeptbean iddept classcom.atguigu.spring5.bean.Deptproperty namedname value安保部/property/bean/property
/bean6 注入 array / list / map / set
示例使用 set 方法进行注入
bean idstu classcom.atguigu.spring5.collectiontype.Stu!--数组类型属性注入--property namecoursesarrayvaluejava 课程/valuevalue数据库课程/value/array/property!--list 类型属性注入--property namelistlistvalue张三/valuevalue小三/value/list/property!--map 类型属性注入--property namemapsmapentry keyJAVA valuejava/entryentry keyPHP valuephp/entry/map/property!--set 类型属性注入--property namesetssetvalueMySQL/valuevalueRedis/value/set/property
/beanbean ...!--注入 list 集合类型值是对象--property namecourseListlistref beancourse1/refref beancourse2/ref/list/property
/bean7 自动装配
在 bean 标签后设置属性 autoware可选参数 byName根据属性的名称自动装配和属性名相同的 id 的 bean 对象byType根据属性类型自动装配 bean 对象
8 使用外部文件配置 Bean
以 Druid 数据库连接池的配置为例。
!--引入 context 名称空间--
.......!--引入外部属性文件--
context:property-placeholder locationclasspath:jdbc.properties/
!--配置连接池--
bean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${prop.driverClass}/propertyproperty nameurl value${prop.url}/propertyproperty nameusername value${prop.userName}/propertyproperty namepassword value${prop.password}/property
/bean四 IOC 的 Bean 管理注解
使用注解的目的是简化 xml 配置
1 Spring 针对创建 Bean 对象提供的注解
ComponentServiceControllerRepository
以上注解的功能相同只是用于标识不同层
2 创建对象的步骤
加入依赖包更改 xml 的名称空间略开启组件扫描如果扫描多个包在一个双引号中用逗号隔开 context:component-scan base-packagecom.atguigu/context:component-scan创建类并使用对应的注解
// value的默认值是 userService
Component(value userService) //相当于xml方式的 bean iduserService class../
public class UserService {public void add() {System.out.println(service add.......);}
}3 属性注入 - Autowared
根据属性类型进行自动装配创建 service 和 dao 对象在 service 和 dao 类添加对应的创建对象注解在 service 注入 dao 对象在 service 类添加 dao 类型属性在属性上使用注解不需要为注入属性添加 set 方法
Service // 等同于 Service(valueuserService) 等同于 bean iduserService class...
public class UserService {Autowiredprivate UserDao userDao;public void add() {System.out.println(service add.......);userDao.add();}4 属性注入 - Qualifier
根据名称注入和上面的 Autowired 一起使用用于区别相同类型的不同 Bean
Service
public class UserService {Autowired // 根据类型进行注入Qualifier(value userDaoImpl1) // 根据名称进行注入private UserDao userDao;public void add() {System.out.println(service add.......);userDao.add();}5 属性注入 - Resource
可以实现类型注入、名称注入类型注入不需要加参数名称注入使用 name 参数指定
6 属性注入 - Value
上述三种注入的是对象属性而 Value 可以注入普通类型
Value(value abc)
private String name;7 完全注解开发
使用 Configuration 注解的类代替配置文件使用 ComponentScan(basePackages {...}) 完成组件扫描
Configuration
ComponentScan(basePackages {com.atguigu})
public class SpringConfig {}使用时加载配置类ApplicationContext context new AnnotationConfigApplicationContext(SpringConfig.class);
Test
public void testService2() {// 加载配置类ApplicationContext context new AnnotationConfigApplicationContext(SpringConfig.class);// 后续操作相同UserService userService context.getBean(userService, UserService.class);// ...
}五 AOP 概述
Aspect Oriented Programming面向切面编程本质是动态代理
连接点类中可以被增强的方法切入点实际增强的方法通知增强实际增强的逻辑部分包含 前置通知 / 后置通知 / 环绕通知 / 异常通知增强发生异常时的逻辑 / 最终通知增强部分类似于 finally切面通知应用到切入点的过程
1 动态代理的两种情况
需要代理的类具有接口使用 JDK 动态代理创建接口实现类代理对象向代理类中传入接口的实现类需要代理的类不具有接口使用 GCLIB 动态代理创建其子类的代理对象
2 JDK 动态代理实例
接口与接口的实现
interface Human{String getBelief();void eat(String food);
}class SuperMan implements Human{Overridepublic String getBelief() {return I believe I can fly!;}Overridepublic void eat(String food) {System.out.println(我喜欢吃 food);}
}动态代理类动态代理对象调用原生方法的时候最终实际上调用到的是 invoke() 方法然后 invoke() 方法调用了被代理对象的原生方法。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class DebugInvocationHandler implements InvocationHandler {// 代理类中的真实对象private final Object target;public DebugInvocationHandler(Object target) {this.target target;}/*** 动态代理的核心部分* proxy :动态生成的代理类* method : 与代理类对象调用的方法相对应* args : 当前 method 方法的参数**/public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {//额外操作...Object result method.invoke(self.target, args); //调用的是method的invoke方法//额外操作...return result;}
}获取代理对象的工厂类输入需要被代理的对象输出其代理。即根据对象实例建立代理实例。
public class JdkProxyFactory {public static Object getProxy(Object target) {return Proxy.newProxyInstance(target.getClass().getClassLoader(), // 目标类的类加载target.getClass().getInterfaces(), // 代理需要实现的接口可指定多个new DebugInvocationHandler(target) // 代理对象对应的自定义 InvocationHandler);}
}实际使用一个代理到处使用 public static void main(String[] args) {//被代理的类型1SuperMan superMan new SuperMan();Human proxyInstance (Human) ProxyFactory.getProxyInstance(superMan); // 强转为对应接口的类型// invoke() 方法: 当我们的动态代理对象调用原生方法的时候最终实际上调用到的是 invoke() 方法然后 invoke() 方法代替我们去调用了被代理对象的原生方法。String belief proxyInstance.getBelief();proxyInstance.eat(四川麻辣烫);//被代理的类型2NikeClothFactory nikeClothFactory new NikeClothFactory();ClothFactory proxyClothFactory (ClothFactory); ProxyFactory.getProxyInstance(nikeClothFactory);proxyClothFactory.produceCloth();}六 AspectJ 的使用注解
AspectJ 不是 Spring 的组成部分独立 AOP 框架一般把 AspectJ 和 Spirng 框架一起使用进行 AOP 操作
1 切入点表达式 用于设置增强方法在代理类中的注解的 value 属性 语法规则execution([权限修饰符可选] [返回类型可为*] [类全路径] [方法名称]([参数列表]) ) 举例 1对 com.atguigu.dao.BookDao 类里面的 add 进行增强 execution(* com.atguigu.dao.BookDao.add(…)) 举例 2对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强 execution(* com.atguigu.dao.BookDao.* (…))
2 使用流程
引入依赖略配置 xml更改名称空间开启组件扫描、代理对象生成
beans...!--开启组件扫描--context:component-scan base-packagepojo/context:component-scan!--生成代理对象--aop:aspectj-autoproxy/aop:aspectj-autoproxy
/beans被代理类、原方法、代理类、增强方法注解。用 Aspect 注解代理类
被代理类与原方法
Component(value myClass)
public class MyClass {public void add() {System.out.println(原来的add方法);}
}代理类与增强方法
Component(value enhanceClass)
Aspect
public class EnhanceClass {Before(value execution(* pojo.MyClass.add(..)))public void before() {System.out.println(前置通知);}AfterReturning(value execution(* pojo.MyClass.add(..)))public void afterReturning() {System.out.println(后置通知正常返回时才执行);}After(value execution(* pojo.MyClass.add(..)))public void after() {System.out.println(最终通知无论是否正常返回都执行);}AfterThrowing(value execution(* pojo.MyClass.add(..)))public void afterThrowing() {System.out.println(异常通知);}Around(value execution(* pojo.MyClass.add(..)))public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println(环绕通知前);proceedingJoinPoint.proceed();System.out.println(环绕通知后);}
}
测试过程与结果 Testpublic void testAspect() {ApplicationContext applicationContext new ClassPathXmlApplicationContext(myclass.xml);MyClass myClass applicationContext.getBean(myClass, MyClass.class);myClass.add();}/*
执行结果环绕通知前前置通知未增强的方法环绕通知后最终通知无论是否正常返回都执行后置通知正常返回时才执行
*/3 相同切入点的抽取
对空方法使用注解 Pointcut(value execution(* com.atguigu.spring5.aopanno.User.add(..))) 相同切入点的注解的 value 属性值为 “空方法调用”
Component(value enhanceClass)
Aspect
public class EnhanceClass {Pointcut(valueexecution(* pojo.MyClass.add(..)))public void myPointCut() {}Before(value myPointCut)public void before() {System.out.println(前置通知);}
}
4 完全注解开发
创建配置类代替 xml
Configuration
ComponentScan(basePackages {pojo})
EnableAspectJAutoProxy(proxyTargetClass true)
public class ConfigAop {}七 JdbcTemplate
1 配置
引入依赖使用 xml 配置 Druid 数据库连接池创建 JdbcTemplate并注入数据库连接池 !-- 数据库连接池 --bean iddataSource classcom.alibaba.druid.pool.DruidDataSource destroy-methodcloseproperty nameurl valuejdbc:mysql://localhost:3306/test /property nameusername valueroot /property namepassword value123 /property namedriverClassName valuecom.mysql.cj.jdbc.Driver //bean!--创建jdbctemplate注入数据库连接池--bean idjdbcTemplate classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property/bean创建 Service 类注入 DAO创建 DAO注入 JdbcTemplate 在 xml 中配置组件扫描 context:component-scan base-packagejdbc/context:component-scan
/*Service 类*/
Service(value userService)
public class UserService {Autowiredprivate UserDAO userDAO;// 提供的服务调用对应的 DAO...
}/*DAO 类*/
Component(value userDAO)
public class UserDAOImpl implements UserDAO {Autowiredprivate JdbcTemplate jdbcTemplate;// 单精度的表操作实现...
}2 添加 / 修改 / 删除 操作
在 DAO 中调用 jdbcTemplate 的 update 方法
Component(value userDAO)
public class UserDAOImpl implements UserDAO {Autowiredprivate JdbcTemplate jdbcTemplate;Overridepublic void add(User user) {String sql insert into user values (?, ?, ?, ?, ?);Object[] args {user.getId(), user.getName(), user.getPwd(), user.getAddr(), user.getTel()};int update this.jdbcTemplate.update(sql, args); // 调用 jdbcTemplate.update 进行添加System.out.println(update);}
}测试方法 Testpublic void testAddOneItem() {User user new User(10, 伍佰, 500, 老城路101, 554433);ApplicationContext applicationContext new ClassPathXmlApplicationContext(myclass.xml);UserService userService applicationContext.getBean(userService, UserService.class);userService.addUser(user);}如果要实现批量操作调用 jdbcTemplate 的 batchUpdatebatchUpdate传入的参数1为 sql参数2为ListObject[] 类型其中的每个元素 Object[] 代表一条语句的参数
3 查询值
在 DAO 中调用 jdbcTemplate 的 queryForObject 方法
Component(value userDAO)
public class UserDAOImpl implements UserDAO {Autowiredprivate JdbcTemplate jdbcTemplate;Overridepublic int selectCount() {String sql select count(*) from user;return this.jdbcTemplate.queryForObject(sql, Integer.class);}
}4 查询单个对象
在 DAO 中调用 jdbcTemplate 的 queryForObject 方法需要传入 BeanPropertyRowMapper 对象其作用是将 SQL 查询返回值封装为指定对象默认情况下需要表属性名和类属性名一致
Component(value userDAO)
public class UserDAOImpl implements UserDAO {Autowiredprivate JdbcTemplate jdbcTemplate;Overridepublic User selectById(int id) {String sql select * from user where id ?;User user this.jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapperUser(User.class), id);return user;}
}5 查询多个对象
类似于查询单个对象调用的是 query 方法
Component(value userDAO)
public class UserDAOImpl implements UserDAO {Autowiredprivate JdbcTemplate jdbcTemplate;Overridepublic ListUser selectAll() {String sql select * from user;ListUser userList this.jdbcTemplate.query(sql, new BeanPropertyRowMapperUser(User.class));return userList;}
}八 Spring 事务管理
底层使用了 AOP 原理事务方法更改数据库内容的方法增删改在 Web - Service - DAO 三层结构中推荐把事务注解放在 Service 层Spring 提供了一个事务管理器接口 PlatformTransactionManager 这个接口针对不同的框架提供不同的实现类 1 注解声明式事务管理的步骤
更改 Spring 配置文件创建事务管理器、注入数据源引入名称空间 tx同时开启事务注解 !--创建事务管理器注入数据库连接池--bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property/bean!--开启事务注解--tx:annotation-driven transaction-managertransactionManager/tx:annotation-drivenTransactional 可以用于类注解类中的所有方法也可以用于方法
2 Transactional 的参数配置
propagation事务传播行为多事务方法进行调用这个过程中事务是如何进行管理的isolation隔离级别可选属性 读未提交 / 读提交 / 可重复读 / 串行化timeout超时时间超时后自动回滚以秒为单位默认-1readOnly是否只读默认为 flase如果设置为 true 则只能查询rollbackFor回滚指定出现哪些异常进行回滚noRollbackFor不回滚指定出现哪些异常不执行回滚
3 完全注解的 声明式事务管理
Configuration //配置类
ComponentScan(basePackages com.atguigu) //组件扫描
EnableTransactionManagement //开启事务
public class TxConfig {//创建数据库连接池Beanpublic DruidDataSource getDruidDataSource() {DruidDataSource dataSource new DruidDataSource();dataSource.setDriverClassName(com.mysql.jdbc.Driver);dataSource.setUrl(jdbc:mysql:///user_db);dataSource.setUsername(root);dataSource.setPassword(root);return dataSource;}//创建JdbcTemplate对象Beanpublic JdbcTemplate getJdbcTemplate(DataSource dataSource) {//到ioc容器中根据类型找到dataSourceJdbcTemplate jdbcTemplate new JdbcTemplate();//注入dataSourcejdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}//创建事务管理器Beanpublic DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {DataSourceTransactionManager transactionManager new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return transactionManager;}
}