1. 程式人生 > >Spring框架知識點(二)

Spring框架知識點(二)

目錄: 1.spring的bean管理(註解) (1)使用註解建立物件 (2)使用註解注入屬性 (3)Xml和註解方式混合使用 2.AOP (1)Aop概述 (2)Aop底層原理 (3)Aop操作相關術語 3.spring的aop操作(基於aspectj的xml方式) 4.Log4j介紹 5.Spring整合web專案演示

1.spring的bean管理(註解)

註解介紹 1.程式碼裡面特殊標記,使用註解可以完成功能 2.註解寫法 @註解名稱(屬性名稱=屬性值) 3.註解使用在類上面,方法上面 和 屬性上面

Spring註解開發準備

1 匯入jar包 (1)匯入基本的jar包 在這裡插入圖片描述 2 建立類,建立方法 3 建立spring配置檔案,引入約束 (1)除了ioc基本操作引入的beans約束 (2)做spring的ioc註解開發,還需要引入新的約束 在這裡插入圖片描述

4 開啟註解的掃描

<!--開啟註解掃描 (1)到包裡面掃描類、方法、屬性上面是否有註解-->
	<context:component-scan base-package="cn.itcast.anno"></context:component-scan>
    
    <!--只掃描屬性上面的註解  -->
    <context:annotation-config></context:annotation-config>

註解建立物件

1 在建立物件的類上面使用註解實現 在這裡插入圖片描述 具體操作例項: 類User.java

package cn.itcast.anno;

import org.springframework.stereotype.Component;

@Component(value="user") //<bean id="user" class=""/>
public class User {
	public void add() {
		System.out.println("add...........");
	}
}

配置檔案bean1.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
	
	<!--開啟註解掃描 (1)到包裡面掃描類、方法、屬性上面是否有註解-->
	<context:component-scan base-package="cn.itcast.anno"></context:component-scan>
    
    <!--只掃描屬性上面的註解  -->
    <context:annotation-config></context:annotation-config>

</beans>

測試TestAnno.java

package spring_day02;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.itcast.anno.User;

public class TestAnno {

	@Test
	public void test1() {
		ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
		User user = (User) context.getBean("user");
		System.out.println(user);
		user.add();
	}
}

測試結果:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
[email protected]
add...........

2 建立物件有四個註解 在這裡插入圖片描述 (1)@Component (2)@Controller (3)@Service (4)@Repository 目前這四個註解功能是一樣的,都是建立物件。 3 建立物件是單例項還是多例項 在這裡插入圖片描述 註解注入屬性 1 建立UserService類,建立UserDao類,在UserService得到UserDao物件 (1)注入屬性第一個註解@Autowired (2)注入屬性的第二個註解@Resource(name=“dao”)name屬性值寫的是註解建立dao物件的value值 具體實現過程: UserDao.java

package cn.itcast.anno;

import org.springframework.stereotype.Component;

@Component(value="dao")
public class UserDao {

	public void add(){
		System.out.println("dao.......");
	}
}

UserService.java

package cn.itcast.anno;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service(value = "userService")
public class UserService {

	// 得到dao物件
	// 1 定義dao型別屬性
	// 在dao屬性上面使用註解 完成物件注入
	@Autowired
	private UserDao userDao;

	// 使用註解方式時候不需要set方法
	public void add() {
		System.out.println("service.....");
		userDao.add();
	}
}

測試

@Test
	public void test2() {
		ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
		UserService userService = (UserService) context.getBean("userService");
		userService.add(); 
	}

結果

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
service.....
dao.......

配置檔案和註解混合使用 1.建立物件操作使用配置檔案方式實現 在這裡插入圖片描述 2.注入屬性的操作使用註解方式實現 在這裡插入圖片描述

AOP概念

1.Aop:面向切面(方面)程式設計,擴充套件功能不修改原始碼實現 2.Aop採用橫向抽取機制,取代了傳統的縱向繼承體系重複性程式碼

AOP原理

縱向機制 在這裡插入圖片描述 橫向機制 在這裡插入圖片描述 在這裡插入圖片描述 AOP操作術語 切面(Aspect): 一個關注點的模組化,這個關注點可能會橫切多個物件。事務管理是J2EE應用中一個關於橫切關注點的很好的例子。在Spring AOP中,切面可以使用基於模式或者基於@Aspect註解的方式來實現。是切入點和通知(引介)的結合。 通知(Advice): 在切面的某個特定的連線點上執行的動作。其中包括了“around”、“before”和“after”等不同型別的通知(通知的型別將在後面部分進行討論)。許多AOP框架(包括Spring)都是以攔截器做通知模型,並維護一個以連線點為中心的攔截器鏈。所謂通知是指攔截到Joinpoint之後所要做的事情就是通知,通知分為前置通知,後置通知,異常通知,最終通知,環繞通知(切面要完成的功能)。 切入點(Pointcut): 匹配連線點的斷言。通知和一個切入點表示式關聯,並在滿足這個切入點的連線點上執行(例如,當執行某個特定名稱的方法時)。切入點表示式如何和連線點匹配是AOP的核心:Spring預設使用AspectJ切入點語法。所謂切入點是指我們要對哪些Joinpoint進行攔截的定義。 連線點(Joinpoint): 在程式執行過程中某個特定的點,比如某方法呼叫的時候或者處理異常的時候。在Spring AOP中,一個連線點總是表示一個方法的執行。類裡面可以被增強的方法,這些方法成為連線點。 引入(Introduction): 用來給一個型別宣告額外的方法或屬性(也被稱為連線型別宣告(inter-type declaration))。Spring允許引入新的介面(以及一個對應的實現)到任何被代理的物件。例如,你可以使用引入來使一個bean實現IsModified介面,以便簡化快取機制。引介是一種特殊的通知,在不修改類程式碼的前提下,Introduction可以在執行期為類動態的新增一些方法或Field。 目標物件(Target Object): 被一個或者多個切面所通知的物件。也被稱做被通知(advised)物件。 既然Spring AOP是通過執行時代理實現的,這個物件永遠是一個被代理(proxied)物件。代理的目標物件(要增強的類)。 AOP代理(AOP Proxy): AOP框架建立的物件,用來實現切面契約(例如通知方法執行等等)。在Spring中,AOP代理可以是JDK動態代理或者CGLIB代理。一個類被AOP織入增強後,就產生一個結果代理類。 織入(Weaving): 把切面連線到其它的應用程式型別或者物件上,並建立一個被通知的物件。這些可以在編譯時(例如使用AspectJ編譯器),類載入時和執行時完成。Spring和其他純Java AOP框架一樣,在執行時完成織入。是把增強應用到目標的過程,把advice應用到target的過程。 在這裡插入圖片描述

通知型別

前置通知(Before advice) 在某連線點之前執行的通知,但這個通知不能阻止連線點之前的執行流程(除非它丟擲一個異常)。 後置通知(After returning advice) 在某連線點正常完成後執行的通知:例如,一個方法沒有丟擲任何異常,正常返回。 異常通知(After throwing advice) 在方法丟擲異常退出時執行的通知。 最終通知(After (finally) advice) 當某連線點退出的時候執行的通知(不論是正常返回還是異常退出)。 環繞通知(Around Advice) 包圍一個連線點的通知,如方法呼叫。這是最強大的一種通知型別。環繞通知可以在方法呼叫前後完成自定義的行為。它也會選擇是否繼續執行連線點或直接返回它自己的返回值或丟擲異常來結束執行。 環繞通知是最常用的通知型別。和AspectJ一樣,Spring提供所有型別的通知,推薦使用盡可能簡單的通知型別來實現需要的功能。例如,如果你只是需要一個方法的返回值來更新快取,最好使用後置通知而不是環繞通知,儘管環繞通知也能完成同樣的事情。用最合適的通知型別可以使得程式設計模型變得簡單,並且能夠避免很多潛在的錯誤。比如,你不需要在JoinPoint上呼叫用於環繞通知的proceed()方法,就不會有呼叫的問題。 引用原文:https://blog.csdn.net/wangyongxia921/article/details/46627379

Spring的aop操作聯合aspectj框架

1.在spring裡面進行aop操作,使用aspectj (1)aspectj不是spring一部分,和spring一起使用進行aop操作 (2)Spring2.0以後新增了對AspectJ支援 2.使用aspectj實現aop有兩種方式 (1)基於aspectj的xml配置 (2)基於aspectj的註解方式 AOP操作準備 1.除了匯入基本的jar包外,還需要匯入aop相關的jar包 在這裡插入圖片描述 2.建立spring核心配置檔案,匯入aop的約束 在這裡插入圖片描述 使用表示式配置切入點 1.切入點:實際增強的方法 2.常用的表示式 execution(<訪問修飾符>?<返回型別><方法名>(<引數>)<異常>) (1)execution(cn.itcast.aop.Book.add(…)) 第一個代表任何訪問修飾都行 (2)execution(cn.itcast.aop.Book.(…)) 指定類中任何訪問修飾符的所有方法 (3) execution(* .(…)) 表示 對所有類的所有方法進行增強 (4)execution(save(…)) 匹配所有save開頭的方法 基於Aspectj的aop操作 在這裡插入圖片描述 使用表示式配置增強通知例項 Book.java

package cn.itcast.aop;

//被增強的類
public class Book {

	public void add() {
		System.out.println("add.....");
	}
}

MyBook.java

package cn.itcast.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyBook {

	public void before1() {
		System.out.println("前置增強........");
	}
	
	public void after1(){
		System.out.println("後置增強.........");
	}
	
	//環繞通知
	public void around1(ProceedingJoinPoint pj) throws Throwable{
		//方法之前
		System.out.println("方法之前............");
		
		//執行被增強的方法
		pj.proceed();
		
		//方法之後
		System.out.println("方法之後............");
	}
}

配置檔案

<?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/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
	<!--1.配置物件 -->
	<bean id="book" class="cn.itcast.aop.Book"></bean>
	<bean id="myBook" class="cn.itcast.aop.MyBook"></bean>
	<!--2.配置aop操作 -->
	<aop:config>
		<!--2.1 配置切入點 -->
		<!--注意點:配置中的第一個星號(*)代表資料型別,因此中間需要一個空格 -->
		<aop:pointcut expression="execution(* cn.itcast.aop.*.*(..))"
			id="pointcut1" />

		<!--2.2 配置切面 把增強用到方法上面 -->
		<!--ref 寫增強類物件 -->
		<aop:aspect ref="myBook">
			<!--配置增強的型別 method:增強類中使用哪個方法作為前置 -->
			<aop:before method="before1" pointcut-ref="pointcut1" />
			<!--配置後置增強(後置通知) -->
			<aop:after-returning method="after1"
				pointcut-ref="pointcut1" />
			<!--配置環繞增強 -->
			<aop:around method="around1" pointcut-ref="pointcut1" />
		</aop:aspect>
	</aop:config>
</beans>

測試

package spring_day02;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.itcast.aop.Book;

public class AopTest {
	@Test
	public void Test() {
		ApplicationContext con = new ClassPathXmlApplicationContext("bean3.xml");
		Book book = (Book) con.getBean("book");
		book.add();
	}
}

結果

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
前置增強........
方法之前............
add.....
方法之後............
後置增強.........

Log4j介紹

1.通過log4j可以看到程式過程中更詳細的資訊 (1)經常使用log4j檢視日誌 2.使用 (1)匯入log4j的jar包 (2)複製log4j的配置檔案,賦值到src下面(在src下面建立log4j.properties配置檔案) 在這裡插入圖片描述 3.設定日誌級別 在這裡插入圖片描述 (1)info:看到基本資訊 (2)debug:看到更詳細的資訊 Spring整合web專案演示 1.演示問題 (1)action呼叫service , service呼叫dao (2)每次訪問action的時候,都會載入spring配置檔案,效能大大降低 在這裡插入圖片描述 2.解決方法 (1)在伺服器啟動的時候,建立物件載入配置檔案 (2)底層使用監聽器、Servletcontext物件 3.在spring裡面不需要我們自己寫程式碼實現,spring自己封裝了 (1)封裝了一個監聽器,只需要配置監聽器就可以了(web.xml進行配置) (2)配置監聽器之前需要匯入spring整合web專案的jar包 在這裡插入圖片描述 (3)在web.xml檔案中可用快捷鍵Ctrl+Shift+t在這裡插入圖片描述 在這裡插入圖片描述 (4)指定載入spring配置檔案的位置 因為spring官方預設的檔名稱及路徑如下: 在這裡插入圖片描述 (5)在web.xml檔案指定sprin配置檔案路徑

<!--指定spring配置檔案位置  -->
	<context-param>
	 <param-name>contextConfigLocation</param-name>
	 <param-value>classpath:bean1.xml</param-value>
	</context-param>

啟動伺服器,通過日誌檔案可以檢視到,伺服器啟動的時候就啟動物件載入配置檔案進行物件建立: 在這裡插入圖片描述 實力專案結構圖: 在這裡插入圖片描述 所需jar包: 在這裡插入圖片描述 例項程式碼: UserAction.java

package cn.itcast.action;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.opensymphony.xwork2.ActionSupport;

import cn.itcast.service.UserService;

public class UserAction extends ActionSupport {

	@Override
	public String execute() throws Exception {
		System.out.println("action...........");
		ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
		UserService userService = (UserService) context.getBean("userService");
		userService.add(); // 呼叫UserService的方法
		return NONE;
	}
}

UserDao.java

package cn.itcast.dao;

public class UserDao {

	public void add() {
		System.out.println("dao.......");
	}
}

UserService.java

package cn.itcast.service;

import cn.itcast.dao.UserDao;

public class UserService {

	private UserDao userDao;

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public void add() {
		System.out.println("service......");
		userDao.add();  //呼叫UserDao中的add()方法
	}
}

bean1.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

	<bean id="userService" class="cn.itcast.service.UserService">
		<property name="userDao" ref="userDao"></property>
	</bean>
	<bean id="userDao" class="cn.itcast.dao.UserDao"></bean>

</beans>

log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=info, stdout

struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC 
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<package name="demo1" extends="struts-default" namespace="/">
		<action name="userAction" class="cn.itcast.action.UserAction"></action>
	</package>
</struts>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	<display-name>spring_day02_webdemo</display-name>
	<!--指定spring配置檔案位置  -->
	<context-param>
	 <param-name>contextConfigLocation</param-name>
	 <param-value>classpath:bean1.xml</param-value>
	</context-param>
	
	<!--配置struts 2框架的核心Filter -->
	<filter>
		<!--過濾器名 -->
		<filter-name>struts2</filter-name>
		<!-- 配置Struts 2.3.16的核心Filter的實現類 -->
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>
	<!-- 讓Struts 2的核心Filter攔截所有請求 -->
	<filter-mapping>
		<!--過濾器名 -->
		<filter-name>struts2</filter-name>
		<!-- 匹配所有請求 -->
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
	<!--配置監聽器  -->
	<listener>
	  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
</web-app>