Spring 5基礎
- spring是一個輕量級的,非入侵式的框架
- 控制反轉(IOC),面向切面程式設計(AOP)
1.IOC 推導
package com.jf.dao;
public interface UserDao {
void getUser();
}
package com.jf.dao;
public class UserDaoImpl implements UserDao{
@Override
public void getUser() {
System.out.println("獲取預設使用者的資料");
}
}
package com.jf.service;
public interface UserService {
void getUser();
}
package com.jf.service;
import com.jf.dao.UserDao;
import com.jf.dao.UserDaoImpl;
import com.jf.dao.UserDaoMysqlIpml;
public class UserServiceImpl implements UserService{
private UserDao userDao;
@Override
public void getUser() {
userDao.getUser();
}
//利用set進行動態實現值的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
import com.jf.dao.UserDaoMysqlIpml;
import com.jf.dao.UserDaoOracleImpl;
import com.jf.service.UserServiceImpl;
public class MyTest {
public static void main(String[] args) {
//使用者實際呼叫的是業務層,dao層不需要接觸
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoOracleImpl());
userService.getUser();
}
}
2.hello Spring
package com.jf.pojo;
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--使用Spring來建立物件,在spring這些都稱為Bean
型別 變數名 = new 型別()
Bean = 物件 new Hello()
id=變數名
class= new 的物件
property 相當於給物件中的屬性設定一個值
-->
<bean id="hello" class="com.jf.pojo.Hello">
<property name="str" value="Spring"/>
</bean>
</beans>
import com.jf.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//獲取Spring的上下文物件
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.toString());
}
}
3.IOC建立物件的方式
1.使用無參構造建立物件,預設
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 第一種 下標賦值-->
<!-- <bean id="user" class="com.jf.pojo.User">-->
<!-- <constructor-arg index="0" value="張二"/>-->
<!-- </bean>-->
<!-- 第二種透過型別建立不建議使用-->
<!-- <bean id="user" class="com.jf.pojo.User">-->
<!-- <constructor-arg type="java.lang.String" value="張三"/>-->
<!-- </bean>-->
<!-- 第三種,直接透過引數名來設定-->
<bean id="user" class="com.jf.pojo.User">
<constructor-arg name="name" value="張三"/>
</bean>
</beans>
4.Spring 配置
別名
<alias name="user" alias="usrNew"/>
bean配置
<!-- id:bean的唯一識別符號 也就是物件名
class:bean物件所對應的許可權命名
name:也是別名
-->
<bean id="user" class="com.jf.pojo.User" name="userNew">
<constructor-arg name="name" value="張三"/>
</bean>
import
一般用於團隊開發,可以將多個配置檔案,匯入合併為一個
<import resource="bean2.xml"/>
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
5.DI依賴注入環境
SET方式注入
- 依賴 :bean物件的建立依賴於容器
- 注入 :bean物件中所有屬性,由容器決定
package com.jf.pojo;
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
package com.jf.pojo;
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbys() {
return hobbys;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address.toString() +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="address" class="com.jf.pojo.Address">
<property name="address" value="雲南"/>
</bean>
<bean name="student" class="com.jf.pojo.Student">
<property name="name" value="張三"/>
<!-- bean注入,ref-->
<property name="address" ref="address"/>
<!-- 陣列注入-->
<property name="books">
<array>
<value>西遊記</value>
<value>紅樓夢</value>
<value>水滸傳</value>
</array>
</property>
<property name="hobbys">
<list>
<value>聽歌</value>
<value>自駕遊</value>
<value>旅遊</value>
</list>
</property>
<property name="card">
<map>
<entry key="銀行卡" value="12341234"/>
<entry key="身份證" value="12345123451234"/>
</map>
</property>
<property name="games">
<set>
<value>寫字</value>
<value>程式碼</value>
</set>
</property>
<property name="wife">
<null/>
</property>
<property name="info">
<props>
<prop key="學號">20151239</prop>
<prop key="性別">男</prop>
<prop key="username">root</prop>
<prop key="password">root</prop>
</props>
</property>
</bean>
</beans>
import com.jf.pojo.Student;
import com.jf.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.toString());
}
}
6.bean 的作用域
原型模式:(Spring預設模式)
<bean id="user" class="com.jf.pojo.User" name="userNew" scope="prototype">
單例模式;(每次從容器中get的時候,都會產生一個新的物件)
<bean id="user" class="com.jf.pojo.User" name="userNew" scope="singleton">
request,session,application只能在web開發總用到
7.Bean 的自動裝配
- 自動裝配是Spring 滿足bean依賴一種方式
- Spring會在上下文中自動尋找,並自動被bean裝配屬性
在Spring中有三種裝配的方式
1.在xml中顯示的配置
2.在java中顯示配置
3.隱式的自動裝配
搭建環境
package com.jf.pojo;
public class Cat {
public void shout(){
System.out.println("miao");
}
}
package com.jf.pojo;
public class Dog {
public void shout(){
System.out.println("wang");
}
}
<bean id="cat" class="com.jf.pojo.Cat"/>
<bean id="dog" class="com.jf.pojo.Dog"/>
<bean id="people" class="com.jf.pojo.people">
<property name="name" value="小k"/>
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
</bean>
import com.jf.pojo.Student;
import com.jf.pojo.User;
import com.jf.pojo.people;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
people people = context.getBean("people", people.class);
people.getCat().shout();
people.getDog().shout();
}
}
byName
<!-- byname:會自動在上下文中查詢,和自己物件set方法後面的值對應的beanid-->
<bean id="people" class="com.jf.pojo.people" autowire="byName"/>
byType
<bean class="com.jf.pojo.Cat"/>
<bean class="com.jf.pojo.Dog"/>
<!-- byname:會自動在上下文中查詢,和自己物件set方法後面的值對應的beanid
byType:會自動在上下文中查詢,和自己物件屬性型別相同的bean
-->
<bean id="people" class="com.jf.pojo.people" autowire="byType">
<property name="name" value="小k"/>
</bean>
</beans>
小結:
byname:需要保證所有的bean的id唯一,並且這個bean需要和自動注入的屬性的set方法的值一致
bytype:需要保證所有的class唯一,並且這個bean需要和自動注入的屬性的型別一致
7.1使用註解自動裝配
使用註解須知:
1.匯入約束
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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired
可以直接上屬性上使用,也可以在set方式中使用
使用Autowired可以不用編寫set方法,前提是這個自動裝配的屬性在Spring容器中使用,且符合名字byname
如果@Autowired自動裝配的環境比較複雜,自動裝配無法透過一個註解@Autowired完成的時候,可以使用
@Qualifier(value = "值")取配置Autowired的使用,指定一個唯一的bean物件注入
@Autowired
@Qualifier(value = "dog222")
private Dog dog;
<bean id="dog" class="com.jf.pojo.Dog"/>
<bean id="dog222" class="com.jf.pojo.Dog"/>
8 使用註解開發
1.導包
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/context/spring-aop.xsd
2.屬性注入
package com.jf.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//Component 元件等價於<bean id="user" class="com.jf.pojo.User"/>
@Component
public class User {
public String name;
// 等價於<property name="name" value="張三"/>
@Value("張yi")
public void setName(String name) {
this.name = name;
}
}
3.衍生的註解
@Component有幾個衍生的註解,web開發中,會安照mvc三層架構分層
-
dao (@Repository)
-
service (@Service)
-
controller(@controller)
這四個註解的功能都是一樣的,都是代表將某個類註冊到Spring中,裝配bean
4.作用域
@Scope("singleton")
5.小結
xml域與註解
-
xml用來管理bean
-
註解只負責完成屬性的注入
-
使用的時候,必須讓註解生效,需要開啟註解的支援
-
<!-- 指定要掃描的包,這個包下的註解就會生效--> <context:component-scan base-package="com.jf"/> <context:annotation-config/>
9.使用java的方式配置Spring
package com.jf.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//Component的意思是被Spring接管了,註冊到了這個容器中
@Component
public class User {
@Value("張")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
package com.jf.config;
import com.jf.pojo.User;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
//意思是被Spring接管了,註冊到了這個容器中,@Configurable代表是一個配置類,就和我們之前的bean.xml
@Configurable
@ComponentScan("com.jf.pojo")
@Import(AppConfig2.class)
public class AppConfig {
//註冊一個bean 就相當於寫的一個bean標籤
//這個方法的名字,就相當於bean標籤中id屬性
//這個方法的返回值,就相當於bean標籤中的class屬性
@Bean
public User getUser(){
return new User();//就是返回要注入到bean的物件
}
}
package com.jf.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig2 {
}
import com.jf.config.AppConfig;
import com.jf.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
//如果完全使用了配置類方式,就只能ApplicationContext上下文獲取容器,透過配置類的class物件載入
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
User getUser = (User) context.getBean("getUser");
System.out.println(getUser.getName());
}
}
10.代理模式
代理是SpringAOP的底層
代理模式分類
- 靜態代理
- 動態代理
10.1靜態代理
角色分析
-
抽象角色:一般會使用介面或者使用抽象類解決
-
真實角色:被代理角色
-
代理角色:代理真實角色,一般會做一些附屬操作
-
客戶:訪問代理物件的人
程式碼步驟:
1.介面
package com.jf.demo01;
public interface Rent {
public void rent();
}
2.真實角色
package com.jf.demo01;
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房東出租房子");
}
}
3.代理角色
package com.jf.demo01;
public class Proxy implements Rent{
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
@Override
public void rent() {
host.rent();
seeHost();
fare();
}
public void seeHost(){
System.out.println("看房");
}
public void fare(){
System.out.println("收中介費");
}
}
4.客戶端訪問代理角色
package com.jf.demo01;
public class Client {
public static void main(String[] args) {
Host host = new Host();
//代理 代理角色一般會有一些附屬操作
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
代理模式的好處:
- 可以使真實角色的操作更加純粹,不用去關注一些公共的業務
- 公共也就交給代理角色,實現業務的分工
- 公共業務發生擴充套件的時候,方便集中管理
缺點:
- 一個真實角色就會產生一個代理角色;程式碼量會翻倍
加深理解:
package com.jf.demo02;
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
package com.jf.demo02;
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加使用者");
}
@Override
public void delete() {
System.out.println("刪除一個使用者");
}
@Override
public void update() {
System.out.println("修改一個使用者");
}
@Override
public void query() {
System.out.println("查詢一個使用者");
}
}
package com.jf.demo02;
public class UserServiceProxy implements UserService{
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
public void add() {
log("add");
userService.add();
}
@Override
public void delete() {
log("delete");
userService.delete();
}
@Override
public void update() {
log("update");
userService.update();
}
@Override
public void query() {
log("query");
userService.query();
}
public void log(String msg){
System.out.println("使用了"+msg+"方法");
}
}
package com.jf.demo02;
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy();
proxy.setUserService(userService);
proxy.add();
}
}
10.2動態代理類
動態代理的代理類是動態生成的,不是直接寫好的
動態代理類分為兩大類:
- 基於介面的動態代理---JDK動態代理
- 基於類的:cglib
- java位元組碼實現:javasist
需要了解兩個類:Proxy:代理 InvocationHandler:呼叫處理程式
InvocationHandler
package com.jf.demo03;
public interface Rent {
public void rent();
}
package com.jf.demo03;
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房東出租房子");
}
}
package com.jf.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//自動生成代理類
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的介面
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成得到代理類
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
//處理代理例項,並返回結果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//動態代理的本質,就是使用反射機制實現
seeHouse();
Object result = method.invoke(rent, args);
fare();
return result;
}
public void seeHouse(){
System.out.println("中介看房子");
}
public void fare(){
System.out.println("收中介費");
}
}
package com.jf.demo03;
public class Client {
public static void main(String[] args) {
//真實角色
Host host = new Host();
//代理角色:沒有
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//透過呼叫程式處理角色來處理我們要呼叫的介面物件
pih.setRent(host);
Rent proxy = (Rent) pih.getProxy();//得到代理類,這裡代理類是動態生成的
proxy.rent();
}
}
通用理解:
package com.jf.demo02;
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
package com.jf.demo02;
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加使用者");
}
@Override
public void delete() {
System.out.println("刪除一個使用者");
}
@Override
public void update() {
System.out.println("修改一個使用者");
}
@Override
public void query() {
System.out.println("查詢一個使用者");
}
}
package com.jf.demo04;
import com.jf.demo03.Rent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//自動生成代理類
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的介面
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理類
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//處理代理例項,並返回結果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//動態代理的本質,就是使用反射機制實現
Object result = method.invoke(target, args);
log(method.getName());
return result;
}
public void log(String msg){
System.out.println("執行了"+msg+"方法");
}
}
package com.jf.demo04;
import com.jf.demo02.UserService;
import com.jf.demo02.UserServiceImpl;
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
//代理角色;不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService);//設定代理的物件
//動態生成代理類
UserService proxy = (UserService) pih.getProxy();
proxy.delete();
}
}
動態代理類的好處:
- 可以使真實角色的操作更加純粹,不用去關注一些公共的業務
- 公共也就交給代理角色,實現業務的分工
- 公共業務發生擴充套件的時候,方便集中管理
- 一個動態代理類代理的是一個介面,一般就是對應的一類業務
- 一個動態代理類可以代替多個類,只要是實現了同一個介面即可
11使用Spring來實現AOP
方式一:使用Spring的api介面
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.jf.service.UserServiceIpml"/>
<bean id="log" class="com.jf.log.Log"/>
<bean id="afterLog" class="com.jf.log.AfterLog"/>
<!--方式一:使用原生Spring API介面-->
<!-- 配置aop:匯入aop的約束-->
<aop:config>
<!-- 切入點expression:表示式execution:要返回的位置(修飾詞,返回值,類名,方法名)-->
<aop:pointcut id="pointcut" expression="execution(* com.jf.service.UserServiceIpml.*(..))"/>
<!-- 執行環繞-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
package com.jf.service;
public interface UserService {
public void add();
public void delete();
public void update();
public void select();
}
package com.jf.service;
public class UserServiceIpml implements UserService {
@Override
public void add() {
System.out.println("增加一個使用者");
}
@Override
public void delete() {
System.out.println("刪除一個使用者");
}
@Override
public void update() {
System.out.println("修改一個使用者");
}
@Override
public void select() {
System.out.println("查詢一個使用者");
}
}
package com.jf.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
//method:要執行的目標物件的方法
//args:引數
//target:目標物件
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被執行了");
}
}
package com.jf.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice {
//returnValue:返回值
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("執行了"+method.getName()+"方法,返回結果為"+returnValue);
}
}
import com.jf.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.delete();
}
}
方式二:自定義來實現AOP(主要是切面)
<!-- 方式二:自定義類-->
<bean id="diy" class="com.jf.diy.DiyPointCut"/>
<aop:config>
<!-- 自定義切面 ref要引用的類-->
<aop:aspect ref="diy">
<!-- 切入點-->
<aop:pointcut id="point" expression="execution(* com.jf.service.UserServiceIpml.*(..))"/>
<!-- 通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
package com.jf.service;
public interface UserService {
public void add();
public void delete();
public void update();
public void select();
}
package com.jf.service;
public class UserServiceIpml implements UserService {
@Override
public void add() {
System.out.println("增加一個使用者");
}
@Override
public void delete() {
System.out.println("刪除一個使用者");
}
@Override
public void update() {
System.out.println("修改一個使用者");
}
@Override
public void select() {
System.out.println("查詢一個使用者");
}
}
package com.jf.diy;
public class DiyPointCut {
public void before(){
System.out.println("方法執行前");
}
public void after(){
System.out.println("方法執行後");
}
}
import com.jf.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.delete();
}
}
方式三:使用註解實現
package com.jf.diy;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect //標註這個類是一個切面
public class AnnotationPointCut {
@Before("execution(* com.jf.service.UserServiceIpml.*(..))")
public void before(){
System.out.println("執行前");
}
@After("execution(* com.jf.service.UserServiceIpml.*(..))")
public void after(){
System.out.println("執行後");
}
//在環繞增強中,我們可以給定一個引數,代表我們要處理的點
@Around("execution(* com.jf.service.UserServiceIpml.*(..))")
public void around(ProceedingJoinPoint jp){
System.out.println("環繞前");
//執行方法
try {
Object proceed = jp.proceed();
Signature signature = jp.getSignature();//獲得簽名
System.out.println("signature"+signature);
System.out.println(proceed);
} catch (Throwable e) {
e.printStackTrace();
}
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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.jf.service.UserServiceIpml"/>
<bean id="log" class="com.jf.log.Log"/>
<bean id="afterLog" class="com.jf.log.AfterLog"/>
<!--方式一:使用原生Spring API介面-->
<!-- 配置aop:匯入aop的約束-->
<!-- <aop:config>-->
<!--<!– 切入點expression:表示式execution:要返回的位置(修飾詞,返回值,類名,方法名)–>-->
<!-- <aop:pointcut id="pointcut" expression="execution(* com.jf.service.UserServiceIpml.*(..))"/>-->
<!--<!– 執行環繞–>-->
<!-- <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>-->
<!-- <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>-->
<!-- </aop:config>-->
<!-- 方式二:自定義類-->
<bean id="diy" class="com.jf.diy.DiyPointCut"/>
<bean id="annotationPointCut" class="com.jf.diy.AnnotationPointCut"/>
<!-- 開啟註解支援-->
<aop:aspectj-autoproxy/>
<!-- <aop:config>-->
<!--<!– 自定義切面 ref要引用的類–>-->
<!-- <aop:aspect ref="diy">-->
<!--<!– 切入點–>-->
<!-- <aop:pointcut id="point" expression="execution(* com.jf.service.UserServiceIpml.*(..))"/>-->
<!--<!– 通知–>-->
<!-- <aop:before method="before" pointcut-ref="point"/>-->
<!-- <aop:after method="after" pointcut-ref="point"/>-->
<!-- </aop:aspect>-->
<!-- </aop:config>-->
</beans>
import com.jf.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.delete();
}
}
12 spring-mybatis
1.編寫資料來源配置
2.sqlSessionFactory
3.SqlSessionTemplate
4.需要給介面加實現類
5.將寫的實現類,注入到Spring中
6.測試
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--DataSource:使用Spring的資料來源替換mybatis的配置
使用spring提供的配置:org.springframework.jdbc.datasource.DriverManagerDataSource
-->
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<!-- 繫結Mybatis配置檔案-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/jf/mapper/*.xml"/>
</bean>
<!-- SqlSessionTemplate:就是使用的sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只能使用構造器注入sqlSessionFactory,因為沒有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
</beans>
package com.jf.mapper;
import com.jf.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
public class UserMapperImpl implements UserMapper{
//我們所有的操作,都使用sqlSession來執行,現在都使用SqlSessionTemplate
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
import com.jf.mapper.UserMapper;
import com.jf.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyTest {
@Test
public void test() throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
for (User user : userMapper.selectUser()) {
System.out.println(user);
}
}
}
package com.jf.mapper;
import com.jf.pojo.User;
import java.util.List;
public interface UserMapper {
public List<User> selectUser();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=繫結一個對應的Dao/Mapper介面-->
<mapper namespace="com.jf.mapper.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user;
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="com.jf.pojo.User" alias="user"/>
</typeAliases>
</configuration>
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--DataSource:使用Spring的資料來源替換mybatis的配置
使用spring提供的配置:org.springframework.jdbc.datasource.DriverManagerDataSource
-->
<import resource="spring-dao.xml"/>
<bean id="userMapper" class="com.jf.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
</bean>
</beans>
.SqlSessionDaoSupport
package com.jf.mapper;
import com.jf.pojo.User;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
@Override
public List<User> selectUser() {
UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
return mapper.selectUser();
}
}
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--DataSource:使用Spring的資料來源替換mybatis的配置
使用spring提供的配置:org.springframework.jdbc.datasource.DriverManagerDataSource
-->
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<!-- 繫結Mybatis配置檔案-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/jf/mapper/*.xml"/>
</bean>
<!--<!– SqlSessionTemplate:就是使用的sqlSession–>-->
<!-- <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">-->
<!--<!– 只能使用構造器注入sqlSessionFactory,因為沒有set方法–>-->
<!-- <constructor-arg index="0" ref="sqlSessionFactory"/>-->
<!-- </bean>-->
</beans>
import com.jf.mapper.UserMapper;
import com.jf.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyTest {
@Test
public void test() throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
for (User user : userMapper.selectUser()) {
System.out.println(user);
}
}
}
13宣告式事務
回顧事務:
- 把一組業務當成一個業務來做,要麼成功,要麼都失敗
- 確保完整性和一致性
事務的ACID原則
- 原子性
- 一致性
- 隔離性
- 永續性
為什麼需要事務?
- 如果不配置事務,可能存在資料提交不一致的情況下
- 不再spring中配置事務,就需要在程式碼中手動配置事務
- 事務在開發中十分重要
匯入jar包
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
package com.jf.pojo;
public class User {
private int id;
private String name;
private String pwd;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
package com.jf.mapper;
import com.jf.pojo.User;
import java.util.List;
public interface UserMapper {
public List<User> selectUser();
//新增一個使用者
public int addUser(User user);
//刪除一個使用者
public int deleteUser(int id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=繫結一個對應的Dao/Mapper介面-->
<mapper namespace="com.jf.mapper.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user;
</select>
<insert id="addUser" parameterType="user">
insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd})
</insert>
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#{id};
</delete>
</mapper>
package com.jf.mapper;
import com.jf.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
//我們所有的操作,都使用sqlSession來執行,現在都使用SqlSessionTemplate
@Override
public List<User> selectUser() {
User user = new User(7, "小王", "1234");
UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
mapper.addUser(user);
mapper.deleteUser(4);
return mapper.selectUser();
}
@Override
public int addUser(User user) {
return getSqlSession().getMapper(UserMapper.class).addUser(user);
}
@Override
public int deleteUser(int id) {
return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
}
}
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<import resource="spring-dao.xml"/>
<bean id="userMapper" class="com.jf.mapper.UserMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="com.jf.pojo.User" alias="user"/>
</typeAliases>
</configuration>
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
<!--DataSource:使用Spring的資料來源替換mybatis的配置
使用spring提供的配置:org.springframework.jdbc.datasource.DriverManagerDataSource
-->
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<!-- 繫結Mybatis配置檔案-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/jf/mapper/*.xml"/>
</bean>
<!--<!– SqlSessionTemplate:就是使用的sqlSession–>-->
<!-- <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">-->
<!--<!– 只能使用構造器注入sqlSessionFactory,因為沒有set方法–>-->
<!-- <constructor-arg index="0" ref="sqlSessionFactory"/>-->
<!-- </bean>-->
<!--配置宣告式事務-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>
<!-- 結合AOP實現事務的植入-->
<!-- 配置事務的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 給哪些方法配置事務-->
<!-- 配置事務的傳播特性-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置事務的切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.jf.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
import com.jf.mapper.UserMapper;
import com.jf.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
for (User user : userMapper.selectUser()) {
System.out.println(user);
}
}
}