Spring知识体系大全(IOC,AOP,JDBC,事务)

    技术2022-07-13  68

    一、准备工作

    1.创建Maven的java项目。

    2.导入java项目的依赖

    <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.3.7.RELEASE</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.2</version> </dependency> </dependencies>

    3.编写applicationContext.xml 文件

    src->main->resources->applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd "> </beans>

    二、使用spring创建bean对象

    不需要再手动new对象

    1.向applicationContext.xml配置文件中加入bean

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd "> <bean id="stu" class="demo.bean.Student"> <property name="name" value="小明"></property> <property name="age" value="18"></property> </bean> </beans>

    2.通过spring的方式获取对象,只能通过空参构造创建

    @Test public void test2(){ // 通过spring的方式获取对象,调用方法 //1 加载spring的配置文件 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //2 通过spring的方式获取对象 Student stu = ac.getBean("stu",Student.class); /* * stu对象是通过ac的getBean方式获取到的。那么这个stu对象就是由spring框架负责创建的 * * 当spring的配置文件applicationContext.xml文件加载后。spring读取 <bean id="" class>的配置 * spring就会根据 class中配置的类全名,反射方式创建对象,在读取<property>中的内容完成赋值 * * 把创建好的对象放到一个容器(类似于map)中储存起来 -------> key:配置时的id value就是spring创建的对象 * * ac.getBean(配置时的id值) 就获取到的容器中储存对象。 * */ System.out.println(stu.getId()+"\t"+stu.getName()+"\t"+stu.getAge()); stu.sayHello(); }

    3.spring创建对象是否单例

    默认是单例,也可更改,加上scope属性

    三、SpringIOC 讲解

    IOC控制反转

    * IOC Inversion of Control 控制反转。 * * 控制反转就是只对象控制权的反转。 * 在没有使用IOC之前,对象的创建都是由应用程序来负责的(程序员在代码中自己new) * 在使用了Spring(spring的IOC)后,对象的创建交给了spring(对象由spring负责创建) * 这种对象的控制器由应用程序转到spring的现象就叫做控制反转。

    DI依赖注入

    依赖注入(Dependency Injection)

    * 类与类的关系: * * 1 继承关系 class A extends B * 2 关联关系 * class A{ * } * * class B{ * private A a; * } * * B类中的成员变量是A类型。 A类和B类是关联关系 * * 3 依赖关系 * * Class C{ * * } * * class D{ * public void fun(C c){ * } * } * * D类中的方法使用C类型。D类和C类就是依赖关系。D依赖C * 要讲解的Spring中依赖注入的依赖是广义上的依赖。 只要A类中使用了B类,就说A类依赖B类型 依赖注入: 不使用spring之前,依赖的对象也是由应用程序来控制(自己new) 使用spring之后,依赖的对象靠spring来注入!!!

    所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,由spring来创建对象,实现对象之间的解耦。

    spring的工厂

    BeanFactory 和ApplicationContext的区别: 1.ApplicationContext是BeanFactory 的子接口,比BeanFactory 拥有更多功能。 2.创建对象的时机不同: ApplicationContext是加载完spring的配置文件后,就创建对象。 BeanFactory 是调用getBean时才创建对象。

    四、属性注入

    set注入

    bean中必须有无参构造,属性有set方法

    <bean id="stu" class="demo.bean.Student" > <property name="name" value="小明"></property> <property name="age" value="18"></property> </bean>

    构造器注入

    bean中必须有有参构造,可以加入get方法获取属性值

    <bean id="car" class="demo.bean.Car"> <constructor-arg name="name" value="宝马"></constructor-arg> <constructor-arg name="color" value="red"></constructor-arg> </bean>

    复杂类型注入,属于set注入

    private String[] arr; private List list; private Set set; private Map map; private Properties prop; <bean id="array" class="demo.bean.Array"> <!--数组--> <property name="arr"> <array> <value>arr1</value> <value>arr2</value> <value>arr3</value> </array> </property> <!--list集合--> <property name="list"> <list> <value>list1</value> <value>list2</value> <value>list3</value> </list> </property> <!--set集合--> <property name="set"> <set> <value>set1</value> <value>set2</value> <value>set3</value> </set> </property> <!--map集合--> <property name="map"> <map> <entry key="map1" value="111"></entry> <entry key="map2" value="222"></entry> <entry key="map3" value="333"></entry> </map> </property> <!--Properties配置文件--> <property name="prop"> <props> <prop key="prop1">111</prop> <prop key="prop2">222</prop> <prop key="prop3">333</prop> </props> </property> </bean>

    五、SpringAOP 讲解

    面向切面编程Aspect Oriented Programming

    AOP名词解释

    目标(Target) 没有增强功能之前的代码(要被增强,要增加新功能) 切面(Aspect) 要增强的新功能(方法),放在切面中 织入(Weaving) 动词,把目标和切面切在一起的动作(把切面切入到目标中) 代理(Proxy) 目标和切面织到一起后形成的新对象(即具有目标的原有功能,有具体增强的新功能) 切入点(PointCut) 目标中所有可以被切面切的地方(一般是目标中的方法)

    连接点(JoinPoint) 当切面真的来切这个切入点了,这个切入点就变成了连接点

    通知(Advice) 告诉切面在哪里(在目标方法调用之前、目标方法调用之后、环绕、抛异常时)去切

    添加依赖

    <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.12</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.12</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.1_3</version> </dependency>

    创建切面类

    public class Aop { public void method(){ System.out.println("切面。。。。。。"); } }

    配置切入

    <bean id="aop" class="demo.aspect.Aop"></bean> <!--配置切入--> <aop:config> <!--切入点--> <aop:pointcut id="allservice" expression="execution(* demo.service.StudentServiceImpl.*(..))"/> <!--切面--> <aop:aspect ref="aop"> <aop:before method="method" pointcut-ref="allservice"></aop:before> </aop:aspect> </aop:config>

    方法命名add*(…):所有以add开头的方法

    效果

    通知说明

    Around通知较为特殊,需要在切面方法中放行目标方法 pjp.proceed();

    <aop:around method="myAround" pointcut-ref="allServiceMethod"/>

    放行目标方法

    public void myAround(ProceedingJoinPoint pjp){ System.out.println("around 环绕 ,在目标方式之前执行###"); try { pjp.proceed(); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } // 调用目标方法 System.out.println("around 环绕 ,在目标方式之后执行####"); }

    获取连接点

    public class Aop { public void method(JoinPoint jp){ jp.getArgs(); // 获取被切的切入点(方法)的参数 String name = jp.getSignature().getName(); //获取被切的切入点(方法)的名字 }

    六、spring整合JDBC

    1.添加依赖

    除了通用的IOC依赖,还有以下依赖

    <!-- druid mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <!-- spring-jdbc spring-tx --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.10.RELEASE</version> </dependency>

    2.书写dao

    public class AddUserImpl implements AddUser{ JdbcTemplate jt; public JdbcTemplate getJt() { return jt; } public void setJt(JdbcTemplate jt) { this.jt = jt; } @Override public int add(User user) { String sql="insert into users values(null,?,?);"; int update = jt.update(sql, user.getUsername(), user.getPassword()); return update; } }

    3.书写配置文件

    <!--配置持久层操作对象--> <bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="ds"></property> </bean> <!--配置持久层--> <bean id="userdao" class="demo.dao.AddUserImpl"> <property name="jt" ref="jdbctemplate"></property> </bean> <!--配置数据源--> <bean id="ds" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="jdbc:mysql:///test"></property> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="username" value="root"></property> <property name="password" value="123456"></property> </bean>

    七、spring注解方式IOC开发

    1.添加配置文件

    <!--开启spring注解方式--> <context:annotation-config></context:annotation-config> <!--设置扫描路径--> <!--spring会为扫描路径下所有添加了@Component注解的类创建spring的bean--> <context:component-scan base-package="demo"></context:component-scan> <!--开启AOP注解--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    2.类上添加注解

    @Component//bean的id默认是类名首字母小写 //@Component("aa") @Scope("prototype") public class Transaction { @Autowired//自动装配,把类型匹配的bean注入 private Car c; @Autowired private Ship s; public Car getC() { return c; } public void setC(Car c) { this.c = c; } public Ship getS() { return s; } public void setS(Ship s) { this.s = s; } }

    3.常用注解

    @Component :添加了这个注解的类会被spring扫描当成 bean来处理 可以设置bean的id : @Component(“起名字bean的id”) 也可以不设置bean的id 默认就是类名首字母变小写

    @Autowired : 自动装配(按类型) 问题:当多个类型符合时,将无法注入

    解决:

    @Scope(“prototype”) 更改单例为每次getBean创建新的对象

    Spring还提供了以下几个注解来替代 @Component @Controller 一般加在控制层 @Service 一般加在业务层 @Repository 一般加在持久层 作用和@Component完全相同(可能会在以后的版本中有不同)

    八、注解方式AOP开发

    1.添加配置文件

    <!-- 开启注解方式的aop --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    2.配置切面注解

    @Component @Aspect//指定切面 public class log { //方法一 @Pointcut("execution(* demo.service.*.*(..))") public void anyMethod(){//写一个随意的方法,目的引入切入点 } //方法二 @Before("execution(* demo.service.*.*(..))")//直接指定切入点 public void before(){ System.out.println("before............"); } @After("execution(* demo.service.*.*(..))") public void after(){ System.out.println("after............"); } @AfterReturning("anyMethod()")//使用上面的方法名指定切入点 public void afterReturn(){ System.out.println("afterReturning............"); } @Around("execution(* demo.service.*.*(..))") public void around(ProceedingJoinPoint jp){ System.out.println("around 1----------"); try { jp.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } System.out.println("around 2------------"); } }

    3.切面注解的两种方式对比

    方式一固定,一旦修改就都改变。 方式二较为灵活。

    九、修改ApplicationContext对象

    1.添加依赖

    2.设置监听器

    监听器ContextLoaderListener的init方法,随着服务器启动,servletContext的创建而执行,让servletContext加载context-param中的参数,加载xml,生成了ApplicationContext对象。

    3.获取applicationContext对象

    避免每次都new,一直使用servletContext中的ApplicationContext

    十、spring事务

    1.配置文件方式事务开发

    配置事务管理器和切入点

    <bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource"></bean> <!-- 配置事务管理器(切面) 目标就是service--> <!-- spring针对不同的持久层提供了不同的事务管理器(切面) jdbc:DataSourceTransactionManager--> <!-- 事务管理器可以控制事务的提交和回滚 需要操作数据库 需要把dataSource注入给事务管理器--> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="ds"></property> </bean> <!-- 定义事务的传播规则--> <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="modify*" propagation="REQUIRED"/> <tx:method name="remove*" propagation="REQUIRED"/> <tx:method name="zhuanzhang" propagation="REQUIRED" no-rollback-for="java.lang.ArithmeticException" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="allServiceMethods" expression="execution(* com.offcn.service.impl.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethods"></aop:advisor> </aop:config>

    2.事务的传播规则

    3.回滚规则

    默认情况下spring的事务管理是碰见异常就回滚 no-rollback-for:碰见这种异常不回滚,其他异常都回滚

    4.注解方式事务开发

    1.配置事务管理器,开启注解方式事务

    <bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource"></bean> <!-- 注解方式的事务管理,事务管理器还是需要配置--> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="ds"></property> </bean> <!--引入事务管理器--> <tx:annotation-driven transaction-manager="dataSourceTransactionManager" proxy-target-class="true"></tx:annotation-driven>

    2.代码 使用@Transactional注解: 可以加在类上,也可以加在方法

    加在类上,这个类中的所有public修饰的方法都会被事务管理 加在方法上,就是这个具体的方法会被事务管理 @Service("accountService") //@Transactional(propagation = Propagation.REQUIRED) // 这种配置,对类中的每个方法都起作用 public class AccountServiceImpl implements AccountService { @Transactional(propagation = Propagation.REQUIRED) // 加在方法上,只对当前方法起作用 public String zhuanzhang(int outId, int inId, int money) {

    5.配置文件方式和注解方式比较

    配置文件方式可以一次对指定的所有切入点添加事务。注解方式需要挨个在每个类上添加,如果类多的情况下,显然麻烦。
    Processed: 0.017, SQL: 9