一、簡介
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.0.RELEASE</version> </dependency>
1.spring全家桶的結構構圖:
-
?Core Container
- core:提供了框架的基本組成部分? 包括ioc和依賴注入功能
- beans:提供了BeanFactory? 實現(xiàn)了工廠模式。方便解耦
- context:上下文內(nèi)容
- expression:提供了強大的表達式語言,用于在運行時查詢和操作對象。
? ? 3.Data Access/Integration 數(shù)據(jù)訪問/集成
- 該模塊包含JDBC、ORM、OXM、JMS和事務處理模塊
- JDBC:提供了JDBC的抽象層,可以更方便的處理數(shù)據(jù)庫
- ORM:模塊提供了流行的對象關系型映射的API的集成
- OXM:模塊提供了對OXM實現(xiàn)的支持(啥是OXM)
- JMS:包含了生產(chǎn)和消費消息的功能
- 事務:毋庸置疑,可以實現(xiàn)特殊接口類以及所有的pojo支持編程式和聲明式事務管理。
?? ? 4.Web
- Web模塊:提供面向web的基本功能和面向web的應用上下文
- Servlet模塊:為web應用提供了模型視圖看著(MVC)和RestWeb服務的實現(xiàn)。Spring的MVC框架可以將代碼與web表單進行分離。
- Web-Socket
- Web-Portlet
二、IOC:
//1.引入jar包
//2.編輯配置文件
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
配置對象 id為唯一限定名 一般為類名的小寫 class是類所在的位置
<bean id="teacher" class="com.qiang.pojo.Teacher"></bean>
</beans>
//3.測試
@Test
public void testTeacherCreate(){
//加載配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
Teacher teacher = ac.getBean("teacher", Teacher.class);
System.out.println(teacher);
}
//在以上代碼中 如果使用的是ApplicationContext 則在進行加載配置文件時 就已經(jīng)在IOC容器中創(chuàng)建好了teacher對象
//如果是使用的是 BeanFactory ac 創(chuàng)建對象,則在getbean時才會創(chuàng)建對象(不可操作,因為該接口不對開發(fā)人員透明)
2.2.3 ApplicationContext接口的實現(xiàn)類的繼承關系
<bean id="唯一標識" class="類的全限定名"> </bean>
? ? ? ? B :使用普通工廠類創(chuàng)建bean實例
1.建立普通類teacher,包含個別屬性,并添加get、set方法
2.創(chuàng)建工廠類
public class SchoolFactory {
Teacher teacher=new Teacher();
public Teacher getInstance(){
return teacher;
}
}
在工廠類中實例化對象,并添加一個普通方法可以獲取到對象
3.配置文件
<!-- 普通工廠類創(chuàng)建bean實例-->
<bean id="factory" class="com.qiang.pojo.factory.SchoolFactory" ></bean>
<bean id="teacher1" factory-bean="factory" factory-method="getInstance"></bean>
第一個bean是一個實例化的對象也就是對象工廠
第二個bean 是利用對象工廠來創(chuàng)建的對象實例化
factory標簽指的是 是哪個工廠對象,對應上邊的id
factory-method指的是調用可以獲取對象實例的方法(普通方法)
4.測試:
/**
* 測試普通工廠類創(chuàng)建bean實例
*/
@Test
public void testTeacherFactory1(){
//加載配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
Teacher teacher1 = ac.getBean("teacher1", Teacher.class);
System.out.println(teacher1);
}
如果在程序中可能需要頻繁的創(chuàng)建某個類的實例對象,采用工廠模式會更好
public class Student {
private String sname;
private int age;
private String sex;
public Student(String sname, int age, String sex) {
this.sname = sname;
this.age = age;
this.sex = sex;
System.out.println("這是三個參數(shù)的無參構造");
}
public Student(String sname, int age) {
this.sname = sname;
this.age = age;
System.out.println("這是第一個屬性為name的兩個參數(shù)的構造");
}
public Student( int age,String sname) {
this.sname = sname;
this.age = age;
System.out.println("這是第一個屬性為age的兩個參數(shù)的構造");
}
public Student() {
System.out.println("這是無參構造");
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"sname='" + sname + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
<bean id="stu1" class="com.qiang.pojo.Student">
<constructor-arg name="sname" value="zs"></constructor-arg>
<constructor-arg name="age" value="15"></constructor-arg>
</bean>
看我們的實體類中就可以發(fā)現(xiàn),我們的含有兩個參數(shù)的構造器,有兩個,在這個時候我們使用的構造器的構造函數(shù)就不知道使用的是哪個帶參的構造器
因此我們可以使用 index來標識下標 就可以指定先執(zhí)行那個代餐的構造
其中constructor-arg中也可以使用type來標識參數(shù)類型來確定屬性
如果是八大基本數(shù)據(jù)類型,則可以直接寫關鍵字,如果是其他類型,則需要添加類的全限定路徑
如果其中還含有其他對象類型的參數(shù),
如此時的student類中包含屬性 private Grade grade;
構造器:
<bean>
<construct-arg type="com.qiang.Grade" ref="grade"></construct-arg>
</bean>
<bean id="grade" class="com.qiang.Grade"></bean>
?B set方法注入? 此時需要在類中對屬性添加set方法 以及無參構造
<bean id="student2" class="com.qiang.pojo.Student"> <property name="id" value="2"></property> <property name="name" value="李四"></property> </bean>
? C :p標簽注入 此時就要添加對應的set方法以及無參構造 以及添加頭文件
? D:也可以set注入和構造器注入 混合使用 但是需要有對應的構造方法
實體類
public class Order {
private String [] cources;
private List<String> lists;
private Map<String,String> maps;
private Set<String> sets;
配置文件
<!-- 測試不同屬性類型的屬性注入-->
<bean id="order" class="com.qiang.pojo.Order">
<!-- 數(shù)組集合使用array標簽-->
<property name="cources">
<array>
<value>美羊羊</value>
<value>蘭羊羊</value>
</array>
</property>
<!-- list集合類型使用list標簽-->
<property name="lists">
<list>
<value>舒克</value>
<value>貝塔</value>
</list>
</property>
<!-- set集合使用set標簽-->
<property name="sets">
<set>
<value>mysql</value>
<value>javase</value>
<value>javaweb</value>
</set>
</property>
<property name="maps">
<map>
<entry key="java" value="我們在學習的語言"></entry>
<entry key="web" value="前端的"></entry>
</map>
</property>
- singleton:默認值? 單例模式 每次獲取的bean都是同一個對象
- prototype:每次獲取bean都會被重新實例化
- request:每次請求都會重新實例化對象,但是在同一請求下獲取的情況下的bean是單例的
- session? 每次會話內(nèi)的bean是單例的
- application:整個應用程序對象內(nèi)的bean實例都是單例模式的
- websocket:同一個websocket對象內(nèi)的對象是單例的。
Singleton
<!-- 測試單例模式-->
<bean id="stu3" class="com.qiang.pojo.Student" scope="singleton"></bean>
測試類:
@Test
public void testStudent3(){
//加載配置文件
BeanFactory ac=new ClassPathXmlApplicationContext("applicationConfig2.xml");
Student stu1 = ac.getBean("stu3", Student.class);
System.out.println(stu1);
Student stu2 = ac.getBean("stu3", Student.class);
System.out.println(stu2);
System.out.println(stu1==stu2);
}
結果:
com.qiang.pojo.Student@10a035a0
com.qiang.pojo.Student@10a035a0
true
prototype
<!-- 測試多例模式-->
<bean id="stu4" class="com.qiang.pojo.Student" scope="prototype"></bean>
測試類
@Test
public void testStudent4(){
//加載配置文件
BeanFactory ac=new ClassPathXmlApplicationContext("applicationConfig2.xml");
Student stu1 = ac.getBean("stu4", Student.class);
System.out.println(stu1);
Student stu2 = ac.getBean("stu4", Student.class);
System.out.println(stu2);
System.out.println(stu1==stu2);
}
結果:
com.qiang.pojo.Student@10a035a0
com.qiang.pojo.Student@67b467e9
false
- 通過構造器創(chuàng)建bean實【此時執(zhí)行的是無參構造】
- 為bean屬性設置值以及對其他的bean的引用【set注入】
- 調用bean的初始化方法,在配置文件中配置
- bean對象可以使用了 【已經(jīng)獲取到了對象】
- 當容器關閉時,調用bean的銷毀方法【在配置文件中配置】
實體類對象
public class People implements Serializable {
private String oid;
public People() {
System.out.println("第一步:執(zhí)行無參構造");
}
public String getOid() {
return oid;
}
public void setOid(String oid) {
this.oid = oid;
System.out.println("第二步: 調用set方法給屬性設置值......");
}
public void initMethod(){
System.out.println("第三步:執(zhí)行初始化方法............");
}
public void destroyMethod(){
System.out.println("第五步:執(zhí)行銷毀方法............");
}
@Override
public String toString() {
return "People{" +
"oid='" + oid + '\'' +
'}';
}
}
配置文件 添加初始化方法 和銷毀方法
<bean id="people" class="com.qiang.pojo.People"
init-method="initMethod"
destroy-method="destroyMethod">
</bean>
其中的標簽init-method、destroy-method 中的方法是在實體類中自定義的
測試類
/**
* 測試bean的生命周期
*/
@Test
public void testBeanLive(){
//加載配置文件
ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig2.xml");
//獲取bean實例
People people = ac.getBean("people", People.class);
System.out.println("第四步:獲取bean實例對象 。。。");
System.out.println(people);
//手動銷毀
ac.close();
}
結果:
第一步:執(zhí)行無參構造
第三步:執(zhí)行初始化方法............
第四步:獲取bean實例對象 。。。
People{oid='null'}
第五步:執(zhí)行銷毀方法............
?文章來源地址http://www.zghlxwxcb.cn/news/detail-488611.html
- 第一步:執(zhí)行無參數(shù)的構造方法 。。。
- 第二步: 調用set方法給屬性設置值......
- 在初始化之前執(zhí)行的方法
- 第三步:執(zhí)行初始化方法............
- 在初始化之后執(zhí)行的方法
- 第四步:獲取bean實例對象 。。。
- 第五步:執(zhí)行銷毀方法............
?文章來源:http://www.zghlxwxcb.cn/news/detail-488611.html
在實體類中 實現(xiàn)了BeanPostProcessor接口
并重寫了
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前執(zhí)行的方法");
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后執(zhí)行的方法");
return bean;
}
?
實體類Dog
private String color;
private int age;
配置文件
<bean id="d1" class="com.qiang.pojo.Dog" autowire="byName">
<property name="age" value="15"></property>
</bean>
測試類:
@Test
public void testDog1(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
Dog d1 = ac.getBean("d1", Dog.class);
System.out.println(d1.getAge());
}
結果:
15
B.byType 按類型自動裝配
配置文件
<bean id="d1" class="com.qiang.pojo.Dog" autowire="byType">
<property name="age" value="21"></property>
</bean>
測試類:
@Test
public void testDog1(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
Dog d1 = ac.getBean(Dog.class);
System.out.println(d1.getAge());
}
結果:
21
?
- Autowired是自動注入,自動從spring的上下文找到合適的bean來注入。
- Resource用來指定名稱注入。
- Qualifier和Autowired配合使用,指定bean的名稱。
- Service,Controller,Repository分別標記類是Service層類,Controller層類,Dao層的類,spring掃描注解配置時,會標記這些類要生成bean。
- Component是一種泛指,標記類是組件,spring掃描注解配置時,會標記這些類要生成bean。
?
分析: 由于注解@Autowired是默認按類型裝配的,一個類型的可能會有多個實現(xiàn)方法
因此在演示的時候 就可以選擇一個接口,有多個實現(xiàn)類來作為演示
1.構建一個接口
public interface TeacherService {
public void sayName();
public void saysex();
}
2.創(chuàng)建多個實現(xiàn)類(以三個舉例)
@Component
public class TeacherServiceImpl1 implements TeacherService {
@Override
public void sayName() {
System.out.println("A");
}
}
@Component
public class TeacherServiceImpl1 implements TeacherService {
@Override
public void sayName() {
System.out.println("B");
}
}
@Component
public class TeacherServiceImpl1 implements TeacherService {
@Override
public void sayName() {
System.out.println("C");
}
}
3.創(chuàng)建兩外一個類,可以調用該類的實現(xiàn)類
public class TeacherController {
@Autowired
//創(chuàng)建對象
private TeacherService teacherService;
public void soutResult(){
teacherService.sayName();
}
}
4.修改配置文件 開啟掃描
<!-- 測試注解開發(fā)-->
<context:component-scan base-package="com.qiang"></context:component-scan>
5.測試:
@Test
public void testAopAno(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
TeacherController contro = ac.getBean("teacherController", TeacherController.class);
contro.soutResult();
}
6.觀察結果:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'teacherController': Unsatisfied dependency expressed through field 'teacherService'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.qiang.service.TeacherService' available: expected single matching bean but found 3: teacherServiceImpl1,teacherServiceImpl2,teacherServiceImpl3
分析:由于在service接口有多個實現(xiàn)類,使用autowired是按類型注入,可能會找不到使用哪個 因此可以搭配使用@Qualifier注解
修改第三步:
public class TeacherController {
@Autowired
@Qualifier("teacherServiceImpl1")
//創(chuàng)建對象
private TeacherService teacherService;
public void soutResult(){
teacherService.sayName();
}
}
繼續(xù)進行測試 結果為:
A
結果顯示正常
繼續(xù)修改第三步:
public class TeacherController {
@Resource(name = "teacherServiceImpl1")
//創(chuàng)建對象
private TeacherService teacherService;
public void soutResult(){
teacherService.sayName();
}
}
繼續(xù)進行測試 結果為:
A
結果顯示正常
?
?
1.添加jar包
2.建造實體類和代理對象類
普通類應包含一個普通方法,該普通方法也就是要增強的那個方法
public class Student implements Serializable {
public void add(){
System.out.println("這個只是一個普通的方法");
}
}
public class StudentProxy {
//配置前置通知
public void before(){
System.out.println("前置通知。。。。。");
}
//配置后置返回通知
public void afterreturning(){
System.out.println("后置返回通知....");
}
//配置最終通知
public void after(){
System.out.println("最終通知....");
}
//配置環(huán)繞通知
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("環(huán)繞通知前");
proceedingJoinPoint.proceed();
System.out.println("環(huán)繞通知后....");
}
//配置異常通知
public void afterThrow(){
System.out.println("異常通知....");
}
}
3.修改配置文件
在修改配置文件時應注意,頭文件也需要進行修改
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd"
//注入
<bean id="student" class="com.qiang.pojo.Student"></bean>
<bean id="studentProxy" class="com.qiang.pojo.StudentProxy"></bean>
<aop:config >
<!--切入點-->
<aop:pointcut id="pc" expression="execution(* com.qiang.pojo.Student.add(..))"/>
<!--配置切面-->
<aop:aspect ref="studentProxy">
<!--將增強應用到具體的方法上-->
<!--前置通知-->
<aop:before method="before" pointcut-ref="pc"></aop:before>
<!--后置返回通知-->
<aop:after-returning method="afterreturning" pointcut-ref="pc"></aop:after-returning>
<!--最終通知-->
<aop:after method="after" pointcut-ref="pc"></aop:after>
<!--環(huán)繞通知-->
<aop:around method="around" pointcut-ref="pc"></aop:around>
</aop:aspect>
以上沒有演示異常通知,異常通知在程序發(fā)生異常時才會發(fā)生。
測試:
@Test
public void testAopXmlDemo1(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
Student student = ac.getBean("student", Student.class);
student.add();
}
結果:
前置通知。。。。。
環(huán)繞通知前
這個只是一個普通的方法
環(huán)繞通知后....
最終通知....
后置返回通知....
1.引入jar包
2.創(chuàng)建實體類
@Component
public class User {
public void add(){
System.out.println("這是一個普通方法");
}
}
3.創(chuàng)建代理類
@Component
@Aspect //生成代理對象
public class UserProxy {
//前置通知
@Before(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
public void before(){
System.out.println("前置通知。。。");
}
//后置返回通知
@AfterReturning(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
public void afterReturning(){
System.out.println("后置返回通知afterReturning....");
}
//環(huán)繞通知
@Around(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("環(huán)繞之前....");
// 被增強的方法執(zhí)行了
proceedingJoinPoint.proceed();
System.out.println("環(huán)繞之后....");
}
// //異常通知 只有手動創(chuàng)造了異常才可以觸發(fā)這個通知
// @AfterThrowing(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
// public void afterThrowing(){
// System.out.println("異常通知 afterThrowing......");
// }
//最終通知
@After(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
public void after(){
System.out.println("最終通知....");
}
}
//修改配置文件
<!-- 開啟組件掃描-->
<context:component-scan base-package="org.qiang.aop.anno"></context:component-scan>
<!-- 開啟Aspect生成代理對象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
//測試:
@Test
public void testAopAnno(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig2.xml");
User user = ac.getBean("user", User.class);
user.add();
}
結果:
環(huán)繞之前....
前置通知。。。
這是一個普通方法
環(huán)繞之后....
最終通知....
后置返回通知afterReturning....
? ? C:第三種方式抽取重復代碼
只需要修改代理類對象就可以了
@Component
@Aspect //生成代理對象
public class UserProxy {
// 抽取切入點
@Pointcut(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
public void pointcutDemo(){
}
//前置通知
@Before(value = "pointcutDemo()")
public void before(){
System.out.println("前置通知。。。");
}
//后置返回通知
@AfterReturning(value = "pointcutDemo()")
public void afterReturning(){
System.out.println("后置返回通知afterReturning....");
}
//環(huán)繞通知
@Around(value = "pointcutDemo()")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("環(huán)繞之前....");
// 被增強的方法執(zhí)行了
proceedingJoinPoint.proceed();
System.out.println("環(huán)繞之后....");
}
// //異常通知 只有手動創(chuàng)造了異常才可以觸發(fā)這個通知
// @AfterThrowing(value = "pointcutDemo()")
// public void afterThrowing(){
// System.out.println("異常通知 afterThrowing......");
// }
//最終通知
@After(value = "pointcutDemo()")
public void after(){
System.out.println("最終通知....");
}
}
?
public void testdemo1() throws SQLException {
Connection conn= DriverManager.getConnection("","","");
//關閉自動提交
conn.setAutoCommit(false);
try {
PreparedStatement ptst=conn.prepareStatement("insert into bank values=(?,?)");
ptst.executeUpdate();
}catch (Exception e){
//再發(fā)生異常時,就會進行事務的回滾
conn.rollback();
}
}
在org.springframework.jdbc.datasource.DataSourceTransactionManager 中的
方法:
protected void doBegin(){
conn.setAutoCommit(false)
}
protected void doBegin() {
}
protected void doRollback() {
}
?
添加事務通知:
<tx:advice id="tt" transaction-manager="transactionmanager"> <tx:attributes> <tx: method name="方法名"> </tx:attributes> </ tx: advice> <aop:config> <aop:pointcut id="pt" expression="execution(* 類的全路徑.方法(. .))" /> <aop:advisor advice-ref="tt" pointcut-ref="pt"> </aop:advisor> </aop:config>
?
?
?
?
?
?
?
?
?
?
到了這里,關于【Java學習】 Spring的基礎理解 IOC、AOP以及事務的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!