Java安全(十三) SSM-Spring框架
概述
Spring 是目前主流的 Java Web 開發框架,是一個輕量級的開源框架,具有很高的凝聚力和吸引力。
Spring 框架不局限于服務器端的開發。從簡單性、可測試性和松耦合的角度而言,任何 Java 應用都可以從 Spring 中受益。Spring 框架還是一個超級粘合平臺,除了自己提供功能外,還提供粘合其他技術和框架的能力。
Spring 是分層的 Java SE/EE 一站式輕量級開源框架,以 IoC(Inverse of Control,控制反轉)和 AOP(Aspect Oriented Programming,面向切面編程)為內核。
- IoC 指的是將對象的創建權交給 Spring 去創建。使用 Spring 之前,對象的創建都是由我們使用 new 創建,而使用 Spring 之后,對象的創建都交給了 Spring 框架。
- AOP 用來封裝多個類的公共行為,將那些與業務無關,卻為業務模塊所共同調用的邏輯封裝起來,減少系統的重復代碼,降低模塊間的耦合度。另外,AOP 還解決一些系統層面上的問題,比如日志、事務、權限等。
在 Spring 中,認為一切 Java 類都是資源,而資源都是類的實例對象(Bean),容納并管理這些 Bean 的是 Spring 所提供的 IoC 容器,所以 Spring 是一種基于 Bean 的編程
Why Spring
如果我們有一個接口
package dao;public interface userdao {void select(); }有兩個實現方法
package dao;public class mysqlimpl implements userdao {@Overridepublic void select() {System.out.println("mysql");} } package dao;public class mssqlimpl implements userdao {@Overridepublic void select() {System.out.println("mssql");} }我們如果要使用的話
package dao;import org.junit.Test;public class test1 {@Testpublic void withoutSpring(){userdao mysqldaoimpl = new mysqlimpl();mysqldaoimpl.select();}}就是前面概述中所說直接new了一個對象,如果在后面想換查詢時還要修改代碼,效率不高,而且這樣寫的話控制權全在開發者手里,而不是在用戶的手里。
Spring使用
快速創建一個maven工程,然后添加spring依賴即可
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.5.RELEASE</version> </dependency>在resources下新建一個bean.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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="mysqlimpl" class="dao.mysqlimpl"/><bean id="mssqlimpl" class="dao.mssqlimpl"/></beans>添加如下的test方法即可
@Testpublic void SpringTest(){ApplicationContext cl = new ClassPathXmlApplicationContext("Bean.xml"); //傳入xml文件userdao mysqldaoimpl = (userdao)cl.getBean("mysqldaoimpl"); //獲取mysqlimpl方法mysqldaoimpl.select();//調用mysqlimpl方法}IoC容器
BeanFactory 容器
BeanFactory 是最簡單的容器,由 org.springframework.beans.factory.BeanFactory 接口定義,采用懶加載(lazy-load),所以容器啟動比較快。BeanFactory 提供了容器最基本的功能。
簡單來說,BeanFactory 就是一個管理 Bean 的工廠,它主要負責初始化各種 Bean,并調用它們的生命周期方法。
BeanFactory 接口有多個實現類,最常見的是 org.springframework.beans.factory.xml.XmlBeanFactory。使用 BeanFactory 需要創建 XmlBeanFactory 類的實例,通過 XmlBeanFactory 類的構造函數來傳遞 Resource 對象。
Resource resource = new ClassPathResource("applicationContext.xml"); BeanFactory factory = new XmlBeanFactory(resource);ApplicationContext 容器
ApplicationContext 繼承了 BeanFactory 接口,由 org.springframework.context.ApplicationContext 接口定義
ApplicationContext 接口有兩個常用的實現類:
ClassPathXmlApplicationContext
該類從類路徑 ClassPath 中尋找指定的 XML 配置文件,并完成 ApplicationContext 的實例化工作,具體如下所示。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);在上述代碼中,configLocation 參數用于指定 Spring 配置文件的名稱和位置,如 Beans.xml。
FileSystemXmlApplicationContext
該類從指定的文件系統路徑中尋找指定的 XML 配置文件,并完成 ApplicationContext 的實例化工作,具體如下所示。
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation);它與 ClassPathXmlApplicationContext 的區別是:在讀取 Spring 的配置文件時,FileSystemXmlApplicationContext 不會從類路徑中讀取配置文件,而是通過參數指定配置文件的位置。即 FileSystemXmlApplicationContext 可以獲取類路徑之外的資源,如“F:/workspaces/Beans.xml”。
Bean
可以把 Spring IoC 容器看作是一個大工廠,Bean 相當于工廠的產品,如果希望這個大工廠生產和管理 Bean,則需要告訴容器需要哪些 Bean,以及需要哪種方式裝配 Bean。
Bean標簽作用:
| id | Bean 的唯一標識符,Spring 容器對 Bean 的配置和管理都通過該屬性完成。id 的值必須以字母開始,可以使用字母、數字、下劃線等符號。 |
| name | name 屬性中可以為 Bean 指定多個名稱,每個名稱之間用逗號或分號隔開。Spring 容器可以通過 name 屬性配置和管理容器中的 Bean。 |
| class | 該屬性指定了 Bean 的具體實現類,它必須是一個完整的類名,即類的全限定名。 |
| scope | 用于設定 Bean 實例的作用域,屬性值可以為 singleton(單例)、prototype(原型)、request、session 和 global Session。其默認值是 singleton |
| init-method | 容器加載 Bean 時調用該方法,類似于 Servlet 中的 init() 方法 |
| constructor-arg | 可以使用此元素傳入構造參數進行實例化 |
依賴注入
Spring 容器在創建被調用者的實例時,會自動將調用者需要的對象實例注入給調用者,調用者通過 Spring 容器獲得被調用者實例,這稱為依賴注入(Dependency Injection,DI)。我們不需要再創建示例了(New)
構造注入
使用類中的構造函數,讓 spring 框架來為我們注入。
Eg:
package User;import java.util.Date;public class Student {private String name;private Integer age;private Date date;public Student() {}public Student(String name, Integer age, Date date) {this.name = name;this.age = age;this.date = date;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Date getDate() {return date;}public void setDate(Date date) {this.date = date;}@Overridepublic String toString() {return "Perpon{" +"name='" + name + '\'' +", age=" + age +", date=" + date +'}';}}xml添加如下
<bean id="person" class="User.Student"><constructor-arg name="name" value="xiaoming"/><constructor-arg name="age" value="18"/><constructor-arg name="date" ref="now"/></bean> <bean id = "now" class="java.util.Date"/>即可測試
@Testpublic void DIConstrutor(){ApplicationContext cl = new ClassPathXmlApplicationContext("Bean.xml"); //傳入xml文件Student person = (Student) cl.getBean("person");System.out.println(person);}在 標簽中,包含 ref、value、type、index 等屬性。value 屬性用于注入基本數據類型以及字符串類型的值;ref 屬性用于注入已經定義好的 Bean;type 屬性用來指定對應的構造函數,當構造函數有多個參數時,可以使用 index 屬性指定參數的位置,index 屬性值從 0 開始。
set注入
<bean id="person" class="User.Student"><property name="name" value="xiaoming"/><property name="age" value="18"/><property name="date" ref="now"/></bean> <bean id = "now" class="java.util.Date"/>在 標簽中,包含 name、ref、value 等屬性。name 用于指定參數名稱;value 屬性用于注入基本數據類型以及字符串類型的值;ref 屬性用于注入已經定義好的 Bean。
Bean自動裝配
Bean 的裝配可以理解為依賴關系注入,Bean 的裝配方式也就是 Bean 的依賴注入方式。自動裝配就是指 Spring 容器在不使用 和 標簽的情況下,可以自動裝配(autowire)相互協作的 Bean 之間的關聯關系,將一個 Bean 注入其他 Bean 的 Property 中。
使用自動裝配需要配置 元素的 autowire 屬性。autowire 屬性有五個值,具體說明如下表所示。
| no | 默認值,表示不使用自動裝配,Bean 依賴必須通過 ref 元素定義。 |
| byName | 根據 Property 的 name 自動裝配,如果一個 Bean 的 name 和另一個 Bean 中的 Property 的 name 相同,則自動裝配這個 Bean 到 Property 中。 |
| byType | 根據 Property 的數據類型(Type)自動裝配,如果一個 Bean 的數據類型兼容另一個 Bean 中 Property 的數據類型,則自動裝配。 |
| constructor | 類似于 byType,根據構造方法參數的數據類型,進行 byType 模式的自動裝配。 |
| autodetect(3.0版本不支持) | 如果 Bean 中有默認的構造方法,則用 constructor 模式,否則用 byType 模式。 |
byNameEg:
package User;public class Student {private String name;private Play play;private Study study;public Student() {}public Student(String name, Play play, Study study) {this.name = name;this.play = play;this.study = study;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Study getStudy() {return study;}public void setStudy(Study study) {this.study = study;}public Play getPlay() {return play;}public void setPlay(Play play) {this.study = study;}}xml添加(XML 文件中 Bean 的 id 必須與類中的屬性名稱相同)
<bean id="person" class="User.Student" autowire="byName"><property name="name" value="xiaoming"/> </bean><bean id="play" class="User.Play"/> <bean id="study" class="User.Study"/>測試一下
@Testpublic void byName(){ApplicationContext cl = new ClassPathXmlApplicationContext("Bean.xml"); //傳入xml文件Student person = (Student) cl.getBean("person");System.out.println(person.getName());person.getPlay().method();person.getStudy().method();}基于注解裝配Bean
如果還是嫌寫Bean太過麻煩,可以用注解的方式,詳細用法可以見:基于注解裝配Bean
Aop
AOP 的全稱是“Aspect Oriented Programming”,即面向切面編程。
通過預編譯方式和運行期間動態代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生范型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。
簡單的說,AOP 的作用就是保證開發者在不修改源代碼的前提下,為系統中的業務組件添加某種通用功能。AOP 就是代理模式的典型應用。
why
相關術語
橫切關注點:對哪些方法進行攔截,攔截后怎么處理,這些關注點稱之為橫切關注點
| Joinpoint(連接點) | 指那些被攔截到的點,在 Spring 中,指可以被動態代理攔截目標類的方法。 |
| Pointcut(切入點) | 指要對哪些 Joinpoint 進行攔截,即被攔截的連接點。 |
| Advice(通知) | 指攔截到 Joinpoint 之后要做的事情,即對切入點增強的內容。 |
| Target(目標) | 指代理的目標對象。 |
| Weaving(植入) | 指把增強代碼應用到目標上,生成代理對象的過程。 |
| Proxy(代理) | 指生成的代理對象。 |
| Aspect(切面) | 切入點和通知的結合。(也是對橫切關注點的抽象) |
AOP實現(AspectJ)
導入相關依賴
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.5</version><scope>runtime</scope> </dependency>接口
package AOP;public interface service {void add();void delete();void update();void qurey(); }實現
package AOP;public class serviceImpl implements service {@Overridepublic void add() {System.out.println("add");}@Overridepublic void delete() {System.out.println("delete");}@Overridepublic void update() {System.out.println("update");}@Overridepublic void qurey() {System.out.println("query");} }不修改代碼的情況下,想增強一下它的功能的話,以前會直接使用動態代理來實現,書寫起來很麻煩。這里就可以使用到aop。
這里再來定義2個方法,分別是方法執行前執行的方法,和方法執行后執行的方法。也叫做前置增強和后置增強
前置:
package AOP;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class log implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println(o.getClass().getName()+"的"+method.getName()+"方法執行了");} }后置
package AOP;import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method;public class afterlog implements AfterReturningAdvice{@Overridepublic void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {System.out.println("執行了"+method.getName()+"執行結果為"+o);} }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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!-- Spring aop 命名空間--><bean id="service" class="AOP.serviceImpl"/><bean id="log" class="AOP.log"/><bean id="afterlog" class="AOP.afterlog"/><aop:config><!-- 聲明切入點,并且使用expression表達式設置需要執行的位置--><aop:pointcut id="pointcut" expression="execution(* AOP.serviceImpl.*(..))"/><!-- advice-ref:設置需要切入的功能,pointcut-ref:設置需要切入的點 --><aop:advisor advice-ref="log" pointcut-ref="pointcut"/><aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/></aop:config></beans>Test
@Testpublic void AOP(){ApplicationContext cl = new ClassPathXmlApplicationContext("Bean_Aspectj.xml");service s = (service) cl.getBean("service");s.add();}也可以將前置增強和后置增強放到一個類中,詳細示例可見:Spring AOP:基于AspectJ XML開發的示例(注意method)
參考鏈接
Java學習之Spring框架入門篇
總結
以上是生活随笔為你收集整理的Java安全(十三) SSM-Spring框架的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 今日头条广告投放技巧干货:落地页分析工具
- 下一篇: 机器人总动员片尾曲歌词_机器人总动员中的