您好,登錄后才能下訂單哦!
基本概念
在沒有Spring之前,程序是通過public UserService user = new UserService()的形式,來給一個變量賦予引用值,user變量定義后就可以直接user.xxx()的來調用方法.
在有Spring之后,可以直接使用public UserService user的形式給來定義變量,而省略new UserService()這一部分,這部分由Spring來進行.
由Spring創建對象,稱其為"控制反轉",Spring創建對象的過程中,發現對象里面還有一個成員變量需要賦值,賦值的過程稱為"依賴注入".
控制反轉
簡稱為IOC,英文全稱:Inversion of Control,為什么原本自己new一個對象
使用注解
告訴了Spring大佬new哪個對象后,如果對象里面有成員變量,還得告訴大佬,得給這個成員變量賦值,具體XML實例如下:
<bean id="mainUI" class="com.jungle.www.controller.MainUI">
<property name="jungle" ref="userService"/>
</bean>
<bean id="userService" class="com.jungle.www.service.serviceimp.UserServiceImpl">
</bean>
<!--
bean標簽,就是用來告訴Spring創建哪個對象
"id" 指定對象名,
"class" 是類的全路徑,寫哪個類,就會創建哪個類的對象.
property標簽,是告訴Spring大佬,創建的對象還有成員變量需要大佬賦值
"name" 需要賦值的成員變量名,Spring給成員變量賦值時,是通過setter 方法來賦值的,所以得給成員變量弄一個setter方法
"ref"代表引用亨達代理申請www.kaifx.cn/broker/hantecglobal.html其他bean的id名所具有的值
這里面有兩個bean,所以創建了兩個對象,分別名叫:mainUI和userService,其中mainUI實例里有一個叫jungle的成員變量,這個成員變量的值是引用了userService,上述的配置,等同于以下:
public void MainUI{
private jungle = new UserServiceImpl();
}
上面的例子里的成員變量,是引用類型,也就是一個對象,那么基本數據類型又如何解決賦值問題?集合又怎樣解決賦值問題?系統的歸納如下:
屬性賦值
value注入基本類型
<bean id="mainUI" class="com.MainUI">
<property name="str" value="李白"/>
</bean>
<!--
//上面的效果,創建了com.MainUI類的名叫mainUI的實例,并且給里面的str成員變量賦值為 李白
public void MainUI{
private String str;
//setter方法省略
}
//下面的實例也是同理
ref 注入已有的bean
官方源碼有一句話:The name of the property, following JavaBean naming conventions,意思就是屬性的名稱,這里就把bean標簽的id當做屬性的的名稱就行了
List\Set\Map
<property name="list">
<list>
<value>J</value>
<value>G</value>
</list>
</property>
<property name="set">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property>
<property name="map">
<map>
<entry key="dock" value="yellow"/>
</map>
</property>
上面通過bean標簽來實例化對象時,默認采用的是無參構造來進行實例化,還有其他幾種方法,也需要知道以下,下面總結一下:
bean的實例化
默認構造器實例化
<bean id="mainUI" class="com.jungle.com.MainUI">
效果:創建了com.jungle.com.MainUI類的名叫mainUI的實例
注意:需要com.jungle.com.MainUI類里具有無參構造!
靜態工廠實例化
<bean id="today" class="com.jungle.com.service" factory-method="getObject"/>
效果:通過com.jungle.com.service類的名叫getObject的靜態方法,創建一個名叫today的實例
實例工廠實例化
//Factory類
public class Factory {
public Robot getRobot(){
return new Robot();
}
}
//Robot類
public class Robot {
public void say(){
System.out.println("i am a robot");
}
}
<!--XML-->
<bean id="robot" factory-bean="factory" factory-method="getRobot"/>
<bean id="factory" class="com.Factory"/>
說明:
第一個bean
id:以后讀取的時候,就是讀取這個id來得到對象
factory-bean:指定生產者
factory-method:指定生產者所使用的方法
第二個bean:創建一個com.Factory類的叫factory的對象
//測試
public static void main( String[] args )
{
ClassPathXmlApplicationContext cpac =
new ClassPathXmlApplicationContext( "applicationContext.xml");
Robot robot = (Robot) cpac.getBean("robot");
robot.say();
}
Spring的FactoryBean接口實例化
類實現FactoryBean<T>接口,重寫getObject()和getObjectType()方法
配置XML文件,bean的實例為getObject方法的返回值
具體實例如下所示:
//java代碼
public class Factory implements FactoryBean<User> {@Override
br/>@Override
return new User(1,"李白","123");}
@Override
br/>}
@Override
return User.class;
}
}
//xml配置
<bean id="user" class="com.jungle.www.controller.Factory"/>
//注:在測試類中,使用getbean("user")即可得到User的實例
當bean已經配置成功后,如何測試呢?
首先得讀取xml配置文件:
ApplicationContext context= new ClassPathXmlApplicationContext( "applicationContext.xml");
然后通過調用其方法,得到對象:
User user = context.getBean("user", User.class)
下面總結一下基本的API吧
核心API
BeanFactory IOC容器的基本接口
ApplicationContext 擴展的IOC容器接口
ClassPathXmlApplicationContext 基于xml配置文件的IOC容器
依賴注入
英文簡稱DI
英文全稱: Dependency Inject
注入方式
setter注入
必須提供setter方法
構造器注入
注:name和index任選一項即可代表你的選擇
bean的作用域
prototype
原型 => 每次創建一個實例
singleton
單例[默認] => 一個bean的定義,只有一個實例,不是一個類只有一個實例
request
一個請求一個實例
session
一個會話一個實例
websocket
一次websocket鏈接一個實例
bean的生命周期
初始化和銷毀
在bean配置上寫init-method和destroy-method
實現InitializingBean和DisposableBean及其方法
在容器關閉的時候銷毀
//例:
public class Cycle2 implements InitializingBean, DisposableBean {@Override
br/>@Override
}
@Override
br/>System.out.println("開始....");
}
@Override
System.out.println("結束了....");
}
}
配置方式
ps:下面的代碼實現,是在IDEA中使用Maven來進行構建和管理,不會Maven的可以去網站:https://how2j.cn/k/idea/idea-maven-config/1353.html學習學習
方式一[純XML實現]
項目結構
APP類
public class App
{
public static void main( String[] args )
{
ClassPathXmlApplicationContext cpac =
new ClassPathXmlApplicationContext(
"applicationContext.xml");
MainUI mainUI = cpac.getBean("mainUI", MainUI.class);
mainUI.mainUI();
}
}
MianUI類
public class MainUI {
private UserService userService;
public void mainUI(){
Scanner temp = new Scanner(System.in);
while(true){
System.out.println("請輸入登錄賬號:");
String account = temp.next();
System.out.println("請輸入登錄密碼:");
String password = temp.next();
User user = userService.judgeUser(account, password);
if(null != user){
System.out.println("登錄成功");
System.exit(0);
}else{
System.out.println("賬號或密碼錯誤,請重新登錄");
}
}
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
在此類中,聲明了UserService類的userService變量,區別于傳統的賦值方式,這里僅僅只是聲明了該變量,根據java的編程規范,未賦值的引用變量,默認值為null.
Spring要做的,就是將userService賦值,而采用xml配置方式,是需要setter方法的,所以在最后添加了一個setUserService方法
UserServiceImpl類
public class UserServiceImpl implements UserService {
private UserDAO userDAO;@Override
br/>@Override
return userDAO.select(account,password);
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
}
代碼分析:有一個變量userDAO需要賦值
UserDAOImpl類
public class UserDAOImpl implements UserDAO {
private QueryRunner qr;@Override
br/>@Override
//建立一個解決數據庫下劃線問題的對象
BasicRowProcessor brp = new BasicRowProcessor(new GenerousBeanProcessor());
//準備sql語句,實際應用時不要用 來查詢,影響效率
String sql = "select from user where user_account=? and user_password=?";
//準備填充數據
Object[] obj = {account,password};
//進行查詢操作
User user = null;
try {
user = qr.query(sql, new BeanHandler<User>(User.class, brp),obj);
} catch (SQLException e) {
throw new RuntimeException("query異常",e);
}
return user;
}
public void setQr(QueryRunner qr) {
this.qr = qr;}
}
此代碼中,有一個名叫qr的成員變量需要賦值,而這里還執行了數據庫的查詢操作,需要在pom.xml文件中引入jar包
User類
@Data
br/>}
}
此代碼中,有一個名叫qr的成員變量需要賦值,而這里還執行了數據庫的查詢操作,需要在pom.xml文件中引入jar包
User類
@Data
br/>@NoArgsConstructor
private int UserId;
private String UserAccount;
private String UserPassword;
}
在這里,使用了lombok來給私有的成員變量建立getter、setter方法和空參構造及有參構造
applicationContext.xml文件配置
<!--在App類中開始啟動,需要得到MainUI類的實例-->
<!--在MainUI類中,存在有叫userService的實例,
所以properties的name代表的就是實例名,ref指引用的地址-->
<bean id="mainUI" class="com.jungle.www.controller.MainUI">
<property name="userService" ref="userService"/>
</bean>
<!--得到UserServiceImpl的實例,UserServiceImpl的實例中存在有叫userDAO的實例-->
<bean id="userService" class="com.jungle.www.service.serviceimp.UserServiceImpl">
<property name="userDAO" ref="UserDAO"/>
</bean>
<!--UserDAOImpl的實例存在有qr的實例,所以得給qr賦值-->
<bean id="UserDAO" class="com.jungle.www.dao.daoimp.UserDAOImpl">
<property name="qr" ref="queryRunner"/>
</bean>
<!--通過構造器(
public QueryRunner(DataSource ds) {
super(ds);
})
得到QueryRunner的實例,需要傳一個DataSouce的實例-->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="druidDataSource"/>
</bean>
<!--德魯伊連接池-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.classDriver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--配置文件-->
<bean id="propertySourcesPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location" value="druid.properties"/>
</bean>
druid.properties文件
jdbc.classDriver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/blog?userUnicode=true&characterEncoding=utf8
jdbc.user=root
jdbc.password=root123
pom.xml文件配置
<!--數據庫_驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--數據庫_工具包-->
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
<!--數據庫_德魯伊連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
<!--SpringFrameWork-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
完整代碼已上傳:
鏈接:https://pan.baidu.com/s/1X64xcNhcqxOkr6sntraiBw
提取碼:upuc
方式二[注解]
通過注解方式可以更加快速配置,只需要在類上面加上注解即可
注冊springbean
@Controller 加在Controller層的實現類上
@Service 加在Service層的實現類上
@Repository 加在Dao層的實現類上@Component加類上,該類就會被Spring識別
br/>@Component加類上,該類就會被Spring識別
生命周期 @PostConstruct @PreDestroy
作用域范圍 @Scope方式三[java配置]
注解:
@Bean
br/>方式三[java配置]
注解:
@Bean
br/>@Configuration
br/>@ComponentScan
加入@Controller…@Autowired
br/>再次簡化
加入@Controller…@Autowired
AOP
Aspect Oritented Programming AOP 面向切面編程
Object Oritened Proguramming OOP 面對對象編程
概念
具有橫切性質的系統功能,例如:日志記錄、性能統計、事務管理、安全檢查等等。散布在系統的各個類中。需要一種機制能將這類功能自動加入到需要的位置中去。這種機制就是AOP。
名詞
連接點 joinpoint 需要加入功能的位置(方法)
切入點 pointcut 執行加入功能的連接點,從連接點選出的需要加入功能的連接點
通知 advice 需要實現的功能
切面 aspect 切入點和通知的組合
目標對象 target 連接點(方法)所在的對象
織入 weave 將切面應用到目標對象的過程
步驟
1) 編寫service類
2) 編寫通知 , 實現MethodBeforeAdvice接口
//method 要執行的方法
// args 方法的參數
// target 方法所在的對象
public void before(Method method, Object[] args, Object target) throws Throwable {
}
3)配置xml
配置service
配置通知
配置切入點,class= org.springframework.aop.support.JdkRegexpMethodPointcut ,配置屬性pattern=> service的方法
配置切面,class=org.springframework.aop.support.DefaultPointcutAdvisor 連接切入點和通知
包裝service類, class= org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
獲取bean,調用方法,將會看到通知執行了
<?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="userService" class="com.jungle.spring.aop.service.impl.UserServiceImpl"/>
<!--通知: 實現了打日志的功能-->
<bean id="beforeExecution" class="com.jungle.spring.aop.component.BeforeExecution"/>
<!--切入點:選出了需要增加功能的方法-->
<bean id="pointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value="com.jungle.spring.aop.service.impl.UserServiceImpl.addUser"/>
</bean>
<!--切面:連接切入點和通知,讓打日志功能在切入點的位置執行-->
<bean id="aspect" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="pointCut"/>
<property name="advice" ref="beforeExecution"/>
</bean>
<!--包裝userService-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
</beans>
通知類型
前置通知 : 方法執行之前 MethodBeforeAdvice
后置通知 : 方法執行之后 AfterReturningAdvice
環繞通知 : 方法執行前后 MethodInterceptor
異常通知 : 拋出異常時
最終通知 : finally執行時
注:面向接口編程 1)解耦,修改實現類 2)默認使用接口的方式生成代理
依賴
aspectj
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
通知類型
前置通知 : 方法執行之前 MethodBeforeAdvice
后置通知 : 方法執行之后 AfterReturningAdvice
環繞通知 : 方法執行前后 MethodInterceptor
異常通知 : 拋出異常時
最終通知 : finally執行時
注:面向接口編程 1)解耦,修改實現類 2)默認使用接口的方式生成代理
依賴
aspectj
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。