Spring注入&AOP
注入
Maven裏面注入Spring
創建最基本的Maven項目,進行依賴注入:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ifueen</groupId>
<artifactId>spring-day02</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--Spring的核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--Context包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--aop的包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--切面的一個包(織入)-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.8</version>
</dependency>
<!-- Spring的測試包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
<!--scope:範圍,只能在test包中使用-->
<!--<scope>test</scope>-->
</dependency>
<!--junit的測試支持-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/test/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
通過構造方法注入參數
<?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="mybean" class="com.ifueen._02constructor.MyBean">
<!-- 通過索引配置-->
<!--<constructor-arg index="0" value="羅素"/>
<constructor-arg index="1" value="3"/>-->
<!-- 通過name配置 -->
<!--<constructor-arg name="age" value="30"/>
<constructor-arg name="name" value="愛倫坡"/>-->
<!-- 通過類型進行配置-->
<!--<constructor-arg type="java.lang.String" value="狄更斯"/>
<constructor-arg type="java.lang.Integer" value="45"/>-->
<!-- 直接根據參數順序進行配置,注意!參數順序一定要相對應-->
<constructor-arg value="薩特"/>
<constructor-arg value="30"/>
</bean>
</beans>
集合&數組&其他屬性的注入
<?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="otherBean" class="com.ifueen._03rest.OtherBean"/>
<bean id="mybean" class="com.ifueen._03rest.MyBean">
<!-- 一般簡單的屬性 -->
<property name="id" value="1"/>
<property name="name" value="山泥若"/>
<property name="sex" value="true"/>
<property name="salary" value="797979"/>
<!-- 數組 -->
<property name="arrays">
<array>
<value>愛倫坡</value>
<value>伏爾泰</value>
<value>羅素</value>
</array>
</property>
<!-- List集合 -->
<property name="list">
<list>
<value>婁燁</value>
<value>王家衛</value>
<value>李安</value>
</list>
</property>
<!-- set集合 -->
<property name="set">
<set>
<value>諾蘭</value>
<value>昆汀</value>
<value>斯皮爾伯格</value>
</set>
</property>
<!-- List集合OtherBean-->
<property name="otherBeanList">
<list>
<!-- 內部Bean -->
<bean class="com.ifueen._03rest.OtherBean"/>
<bean class="com.ifueen._03rest.OtherBean"/>
<!-- 外部引用 -->
<ref bean="otherBean"/>
<ref bean="otherBean"/>
</list>
</property>
<!-- Set集合OtherBean-->
<property name="otherBeanSet">
<list>
<!-- 內部Bean -->
<bean class="com.ifueen._03rest.OtherBean"/>
<bean class="com.ifueen._03rest.OtherBean"/>
<!-- 外部引用 -->
<ref bean="otherBean"/>
<ref bean="otherBean"/>
</list>
</property>
<!-- 簡寫方式 -->
<property name="props1">
<value>
drivenClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///jpa
username=root
password=123456
</value>
</property>
<!-- 標準寫法 -->
<property name="props2">
<props>
<prop key="drivenClassName">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:mysql:///hello</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
<!-- Map集合 -->
<property name="hashMap">
<map>
<entry key="電影" value="2001太空漫步"/>
<entry key="導演" value="庫布里克"/>
</map>
</property>
</bean>
</beans>
使用全註解
使用全註解的方式和之前SpringMVC的使用方式一模一樣
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.ifueen._04auto"/>
</beans>
只需要將掃描包路徑配置好,然後寫三層架構即可
AOP(面向切面編程)
概述
定義:面向切面編程(面向方面編程)
咱們的編程語言從原始機器語言 到過程語言 再到面向對象,從始至終的目的就是爲了讓代碼再加靈活,再加容易讓人理解,構建代碼更加簡單。
AOP的使用只存在於一些特定的場合(具有橫切邏輯的應用場合),橫切邏輯這個解釋可能比較抽象,咱們說得再具體一點,AOP可以用於事務管理,日誌管理,性能監測等地方
面試題:Spring是如何實現AOP?
Spring是使用代理模式來實現AOP的
代理模式分兩種:靜態代理和動態代理
靜態代理太過笨重,一般不太使用
動態代理
Spring提供了兩種方案:JDK和CGLTB
如果目標對象使用了接口就讓JDK來進行代理
如果目標對象沒有使用接口就讓CGLTB來進行代理
使用XML配置實現AOP
首先定義自定義的事務類(僞事務類)
package com.ifueen._05xmlaop;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 自己準備的一個事務
*/
public class TxManager {
public void begin(){
System.out.println("開啓事務");
}
public void commit(){
System.out.println("提交事務");
}
public void rollback(Throwable e){
System.out.println("回滾事務,異常的原因爲"+e.getMessage());
}
public void close(){
System.out.println("關閉資源");
}
public void around(ProceedingJoinPoint point){
/*System.out.println(point.getArgs()); //參數
System.out.println(point.getSignature()); //獲取方法的簽名
System.out.println(point.getTarget().getClass());//真實目標對象
System.out.println(point.getThis().getClass()); //代理對象*/
try {
//開啓事務
begin();
//這裏執行我們自己的代碼
point.proceed();
//提交事務
commit();
} catch (Throwable throwable) {
//回滾
rollback(throwable);
throwable.printStackTrace();
}finally {
//關閉
close();
}
}
}
然後進行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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="myBeanService" class="com.ifueen._05xmlaop.service.impl.MyBeanServiceImpl"></bean>
<bean id="txManager" class="com.ifueen._05xmlaop.TxManager"></bean>
<!-- 配置AOP -->
<aop:config>
<!--
id:切點的名稱
execution是一個表達式,去執行方法
*:代表任意返回值
com.ifueen._05xmlaop.service:對應的包
I*Service:對應的類
*:所有的方法
(..):方法裏面任意參數
-->
<aop:pointcut id="pointcut" expression="execution(* com.ifueen._05xmlaop.service.I*Service.*(..))"/>
<aop:aspect ref="txManager">
<!-- 前置通知 -->
<!--<aop:before method="begin" pointcut-ref="pointcut"></aop:before>-->
<!-- 後置通知 -->
<!--<aop:after-returning method="commit" pointcut-ref="pointcut"></aop:after-returning>-->
<!-- 異常通知,如果要抓取異常的話需要在這裏也要設置 -->
<!--<aop:after-throwing method="rollback" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>-->
<!-- 最終通知 -->
<!--<aop:after method="close" pointcut-ref="pointcut"></aop:after>-->
<!-- 環繞通知 裏面可以自定義-->
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
</aop:aspect>
</aop:config>
</beans>
使用註解配置AOP
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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 掃描包路徑 -->
<context:component-scan base-package="com.ifueen._06annoaop"></context:component-scan>
<!-- 支持AOP註解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
自定義的事務類
package com.ifueen._06annoaop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 註解實現的事務
*/
@Component
@Aspect //AOP的類註解
public class TxManager {
//設置切點
@Pointcut("execution(* com.ifueen._06annoaop.service.I*Service.*(..))")
public void pointcut(){}
//前置通知
/*@Before("pointcut()")*/
public void begin(){
System.out.println("開啓事務");
}
//後置通知
/*@AfterReturning("pointcut()")*/
public void commit(){
System.out.println("提交事務");
}
//異常通知
/*@AfterThrowing(pointcut = "pointcut()",throwing = "e")*/
public void rollback(Throwable e){
System.out.println("回滾事務,異常的原因爲"+e.getMessage());
}
//最終通知
/*@After("pointcut()")*/
public void close(){
System.out.println("關閉資源");
}
//如果要使用環繞通知,需關閉前面的註解,不然可能引起衝突
@Around("pointcut()")
public Object around(ProceedingJoinPoint point){
Object object = null;
try {
//開啓事務
begin();
//這裏執行我們自己的代碼
object = point.proceed();
//提交事務
commit();
} catch (Throwable throwable) {
//回滾
rollback(throwable);
throwable.printStackTrace();
}finally {
//關閉
close();
}
return object;
}
}