Day67 Spring AOP(面向切面程式設計) 和代理設計模式
Spring AOP 概念
Spring AOP學習:
問題:
Spring IOC實現了物件之間依賴關係的解耦。如果開發過程中,需要更改物件,只需要
在配置檔案中更改物件的配置路徑即可完成物件的更換。但是,在保留原有物件的基礎上
對原有功能程式碼進行功能擴充套件,是Spring IOC所不能實現的。
解決:
使用Spring AOP
特點:
在不改變原有物件的功能程式碼的基礎上完成功能擴充套件。
概念:
面向切面的程式設計(擴充套件)。
術語:
前置通知:在原有功能執行之前擴充的程式碼。
後置通知:在原有功能執行之後擴充的程式碼。
切點:原有功能方法
織入:前置通知+切點+後置通知形成切面的過程
切面:前置通知+切點+後置通知形成的橫向執行流程。
使用:
Schema-based方式
Aspectj方式
基於Aspectj的註解方式
流程:
匯入jar包
配置配置檔案
完成擴充套件
Schema-based方式
Schema-Based方式:
第一步:
匯入jar包(Spring IOC包+AOP相關包)
第二步:
在src下建立applicationcontext.xml配置檔案
載入Schema:
<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:myns="http://www.mycompany.com/schema/myns"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
配置相關bean
配置通知bean
配置切面
第三步:
建立通知類
前置通知:
建立一個實現了MethodBeforeAdvice介面的java類
實現介面方法before
引數:
Method arg0:切點方法物件
Object[] arg1:切點接收的實引數組
Object arg2:切點所在的物件
在配置檔案中配置通知bean
在切面配置中配置關聯
後置通知
建立一個實現了AfterReturningAdvice介面的java類
實現介面方法afterReturning
引數:
Object arg0:切點的返回值
Method arg0:切點方法物件
Object[] arg1:切點接收的實引數組
Object arg2:切點所在的物件
在配置檔案中配置通知bean
在切面配置中配置關聯
環繞通知
建立一個實現了MethodInterceptor介面的java類
實現介面方法invoke
引數:
MethodInvocation arg0:放行切點
在配置檔案中配置通知bean
在切面配置中配置關聯
注意:
在實現方法中需要對切點方法進行放行: Object obj=arg0.proceed();//放行,執行切點方法。
異常通知
建立一個實現了ThrowsAdvice介面的java類
實現介面方法afterThrowing
public void afterThrowing(Exception ex) throws Throwable {
System.out.println("我是異常通知");
}
Exception ex:接收的是切點的異常物件。
在配置檔案中配置通知bean
在切面配置中配置關聯
注意:
切點中的內部如果使用異常處理機制,則無法觸發異常通通知。
萬用字元的作用:
1 <aop:pointcut expression="execution(* com.bjsxt.pojo.Car2.demo(..))" id="my"/><!--配置切點 -->
其中切點方式使用..表示引數個數個型別為任意,只要是方法名為demo的都會新增通知。
2 <aop:pointcut expression="execution(* com.bjsxt.pojo.Car2.*(..))" id="my"/><!--配置切點 -->
*是萬用字元,表示任意的方法名,類名,包名等。
第四步:
由Spring容器物件獲取切點所在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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:myns="http://www.mycompany.com/schema/myns"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!-- 配置bean 沒有使用Spring AOP -->
<bean id="car" class="com.bjsxt.pojo.Car"></bean>
<!--配置bean 使用Spring AOP-->
<!--Schema-Based方式 -->
<!--配置切點bean -->
<bean id="car2" class="com.bjsxt.pojo.Car2"></bean>
<!--配置前置通知bean -->
<bean id="before" class="com.bjsxt.advice.MyBefore"></bean>
<!--配置後置通知bean -->
<bean id="after" class="com.bjsxt.advice.MyAfter"></bean>
<!--配置環繞通知bean -->
<bean id="round" class="com.bjsxt.advice.MyRound"></bean>
<!--配置異常通知bean -->
<bean id="throw" class="com.bjsxt.advice.MyThrow"></bean>
<!--配置切面 -->
<aop:config>
<aop:pointcut expression="execution(* com.*.pojo.Car2.*(..))" id="my"/><!--配置切點 -->
<aop:advisor advice-ref="before" pointcut-ref="my"/><!--配置前置通知 -->
<aop:advisor advice-ref="after" pointcut-ref="my"/><!--配置後置通知 -->
<aop:advisor advice-ref="round" pointcut-ref="my"/><!-- 配置環繞通知 -->
<aop:advisor advice-ref="throw" pointcut-ref="my"/><!-- 配置異常通知 -->
</aop:config>
</beans>
基於AspectJ方式
AspectJ方式:
第一步:
匯入jar包(Spring IOC+AOP包)
第二步:
在Src下建立applicationcontext.xml
載入Schema(IOC和AOP相關)
配置相關bean
第三步:
建立通知類
建立一個普通java類,建立四個方法。
前置通知方法
後置通知方法
環繞通知方法
public Object round(ProceedingJoinPoint p) throws Throwable{
System.out.println("AspectJ方式--環繞--前置");
Object obj=p.proceed();
System.out.println("AspectJ方式--環繞--後置");
return obj;
}
異常通知方法
在applicationcontext.xml中配置通知bean
<bean id="advice" class="com.bjsxt.adviceAs.Myadvice"></bean>
在applicationcontext.xml中配置切面
<aop:config>
<aop:aspect ref="advice">
<aop:pointcut expression="execution(* com.bjsxt.pojo.Car3.demo())" id="my1"/><!--配置切點 -->
<aop:before method="before" pointcut-ref="my1"/><!--前置通知 -->
<aop:after-returning method="after" pointcut-ref="my1"/><!--後置通知 -->
<aop:around method="round" pointcut-ref="my1"/><!-- 環繞通知 -->
<aop:after-throwing method="myThrow" pointcut-ref="my1" throwing="e"/><!--異常通知 -->
</aop:aspect>
</aop:config>
第四步:
建立Spring容器物件
獲取切點bean物件
呼叫切點方法
總結:
AspectJ配置方式的通知方法中要獲取切點的引數,配置特別麻煩,切點不能通配。
如果不需要切點的引數則使用AspectJ方式
如果需要引數使用Schema-based方式
-------------------------------------------------------------------------
使用註解(基於AspectJ)
@Component 預設使用無參構造器
Spring預設使用JDK代理模式
基於Aspectj的註解配置AOP:
1 匯入jar包
2 建立Spring配置檔案並完成基礎配置
載入Schema
配置資料來源
配置工廠
配置掃描
3 Spring使用註解配置
在spring配置檔案中增加context的先關Schema
<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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
在Spring配置檔案中配置註解掃描:
<context:component-scan base-package="com.bjsxt.advice,com.bjsxt.pojo"></context:component-scan>
注意:必須在Spring配置檔案中宣告使用了註解的類的包路徑
4 使用註解替換XML的配置
替換bean配置(通用)
@Component
在類名上直接使用此註解,表示bean建立,相當於在Spring中配置了該類的bean標籤。
類名首字母小寫即為bean 的ID
替換切面配置
替換切點宣告
在切點方法上直接使用@Pointcut註解宣告切點,示例如下:
@Pointcut("execution(* com.bjsxt.pojo.Demo.demo())")
public void demo(){
System.out.println("Demo.demo()");
}
替換通知方法的配置
在通知類的類名上還要使用@Aspect進行宣告該類為通知類。
在類的通知方法上使用註解
前置通知:@Before("切點的全限定路徑") 示例:
@Before("com.bjsxt.pojo.Demo.demo()")
public void myBefore(){
System.out.println("註解----前置通知");
}
後置通知
@After("com.bjsxt.pojo.Demo.demo()")
public void after(){
System.out.println("註解---後置通知");
}
環繞通知
@Around("com.bjsxt.pojo.Demo.demo()")
public Object round(ProceedingJoinPoint p) throws Throwable{
System.out.println("註解--環繞--前置");
Object obj=p.proceed();
System.out.println("註解--環繞--後置");
return obj;
}
異常通知
@AfterThrowing("com.bjsxt.pojo.Demo.demo()")
public void myThrow(){
System.out.println("註解---異常");
}
注意:
一定要將動態代理模式設定為cglib代理模式
<!--配置動態代理模式 -->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
--------------------------------------------------------------------------------------------------------------------------------------------
Spring配置檔案中的配置
<?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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--配置註解掃描 -->
<context:component-scan base-package="com.bjsxt.advice,com.bjsxt.pojo"></context:component-scan>
<!--配置動態代理模式 -->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>
切點Bean的配置:
package com.bjsxt.pojo;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
public class Demo {
@Pointcut("execution(* com.bjsxt.pojo.Demo.demo())")
public void demo(){
System.out.println("Demo.demo()");
}
}
通知Bean的配置和切面的配置
package com.bjsxt.advice;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAdvice {
@Before("com.bjsxt.pojo.Demo.demo()")
public void myBefore(){
System.out.println("註解----前置通知");
}
@After("com.bjsxt.pojo.Demo.demo()")
public void after(){
System.out.println("註解---後置通知");
}
@Around("com.bjsxt.pojo.Demo.demo()")
public Object round(ProceedingJoinPoint p) throws Throwable{
System.out.println("註解--環繞--前置");
Object obj=p.proceed();
System.out.println("註解--環繞--後置");
return obj;
}
@AfterThrowing("com.bjsxt.pojo.Demo.demo()")
public void myThrow(){
System.out.println("註解---異常");
}
}
小案例
需求:
匯入包:
aopalliance.jar
asm-3.3.1.jar
aspectjweaver.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
commons-logging-1.1.3.jar
javassist-3.17.1-GA.jar
log4j-1.2.17.jar
log4j-api-2.0-rc1.jar
log4j-core-2.0-rc1.jar
mybatis-3.2.7.jar
mybatis-spring-1.2.3.jar
mysql-connector-java-5.1.30.jar
slf4j-api-1.7.5.jar
slf4j-log4j12-1.7.5.jar
spring-aop-4.1.6.RELEASE.jar
spring-aspects-4.1.6.RELEASE.jar
spring-beans-4.1.6.RELEASE.jar
spring-context-4.1.6.RELEASE.jar
spring-core-4.1.6.RELEASE.jar
spring-expression-4.1.6.RELEASE.jar
spring-jdbc-4.1.6.RELEASE.jar
spring-tx-4.1.6.RELEASE.jar
spring-web-4.1.6.RELEASE.jar
資料庫根據實體類去建立
相關程式碼:
Src:
com.bjsxt.advice:
MyAfter.java:
package com.bjsxt.advice;
import java.lang.reflect.Method;
import java.util.Date;
import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;
public class MyAfter implements AfterReturningAdvice{
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
//建立日誌物件
Logger logger=Logger.getLogger(MyBefore.class);
//校驗
if(arg0!=null){
logger.debug(arg2[0]+"在"+new Date().toLocaleString()+"登陸成功");
}else{
logger.debug("查無此人:"+arg2[0]+":登陸失敗");
}
}
}
MyBefore.java:
package com.bjsxt.advice;
import java.lang.reflect.Method;
import java.util.Date;
import org.apache.log4j.Logger;
import org.springframework.aop.MethodBeforeAdvice;
public class MyBefore implements MethodBeforeAdvice{
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
//建立日誌物件
Logger logger=Logger.getLogger(MyBefore.class);
//輸出日誌
logger.debug(arg1[0]+"在"+new Date().toLocaleString()+"點進行了登陸請求");
}
}
com.bjsxt.mapper:
UserMapper.java:
package com.bjsxt.mapper;
import com.bjsxt.pojo.User;
public interface UserMapper {
//查詢使用者資訊---登入功能
User selUser(String uname,String pwd);
}
UserMapper.xml:
<?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">
<mapper namespace="com.bjsxt.mapper.UserMapper">
<!--根據使用者名稱和密碼查詢使用者資訊 -->
<select id="selUser" resultType="com.bjsxt.pojo.User" >
select * from t_user where uname=#{0} and pwd=#{1}
</select>
</mapper>
com.bjsxt.pojo:
User.java:
package com.bjsxt.pojo;
public class User {
private int uid;
private String uname;
private String pwd;
private String uphone;
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getUphone() {
return uphone;
}
public void setUphone(String uphone) {
this.uphone = uphone;
}
@Override
public String toString() {
return "User [uid=" + uid + ", uname=" + uname + ", pwd=" + pwd + ", uphone=" + uphone + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((pwd == null) ? 0 : pwd.hashCode());
result = prime * result + uid;
result = prime * result + ((uname == null) ? 0 : uname.hashCode());
result = prime * result + ((uphone == null) ? 0 : uphone.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (pwd == null) {
if (other.pwd != null)
return false;
} else if (!pwd.equals(other.pwd))
return false;
if (uid != other.uid)
return false;
if (uname == null) {
if (other.uname != null)
return false;
} else if (!uname.equals(other.uname))
return false;
if (uphone == null) {
if (other.uphone != null)
return false;
} else if (!uphone.equals(other.uphone))
return false;
return true;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(int uid, String uname, String pwd, String uphone) {
super();
this.uid = uid;
this.uname = uname;
this.pwd = pwd;
this.uphone = uphone;
}
}
com.bjsxt.service:
UserService.java:
package com.bjsxt.service;
import com.bjsxt.pojo.User;
public interface UserService {
/**
* 查詢使用者資訊
* @param uname 使用者名稱
* @param pwd 密碼
* @return 返回儲存了使用者資訊的User物件
*/
User selUserService(String uname,String pwd);
}
com.bjsxt.serviceImpl:
UserServiceImpl.java:
package com.bjsxt.serviceImpl;
import com.bjsxt.mapper.UserMapper;
import com.bjsxt.pojo.User;
import com.bjsxt.service.UserService;
public class UserServiceImpl implements UserService {
// 宣告mapper介面屬性
private UserMapper um;
public UserMapper getUm() {
return um;
}
public void setUm(UserMapper um) {
this.um = um;
}
//查詢使用者資訊---登入功能
@Override
public User selUserService(String uname, String pwd) {
return um.selUser(uname, pwd);
}
}
com.bjsxt.servlet:
UserServlet.java:
package com.bjsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.bjsxt.pojo.User;
import com.bjsxt.service.UserService;
/**
* Servlet implementation class UserServlet
*/
@WebServlet("/us")
public class UserServlet extends HttpServlet {
//宣告業務層物件
private UserService us;
//初始化
@Override
public void init() throws ServletException {
//獲取Spring容器物件
ApplicationContext ac=WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
//給業務層物件賦值
us=(UserService) ac.getBean("us");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//設定請求編碼格式
req.setCharacterEncoding("utf-8");
//設定響應編碼格式
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//獲取請求資訊
String uname=req.getParameter("uname");
String pwd=req.getParameter("pwd");
//處理請求資訊
//獲取業務層物件
User u=us.selUserService(uname, pwd);
//響應處理結果
if(u!=null){
resp.sendRedirect("main.jsp");
}else{
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
}
}
applicationcontext.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="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"></property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
</bean>
<!-- 配置工廠-->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置mapper掃描 -->
<bean id="mapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bjsxt.mapper"></property>
<property name="sqlSessionFactory" ref="factory"></property>
</bean>
<!--配置其他bean -->
<!--配置業務bean -->
<bean id="us" class="com.bjsxt.serviceImpl.UserServiceImpl">
<property name="um" ref="userMapper"></property>
</bean>
<!--配置通知bean -->
<bean id="before" class="com.bjsxt.advice.MyBefore"></bean>
<bean id="after" class="com.bjsxt.advice.MyAfter"></bean>
<!--配置切面 -->
<aop:config>
<aop:pointcut expression="execution(* com.bjsxt.serviceImpl.UserServiceImpl.selUserService(..))" id="my"/>
<aop:advisor advice-ref="before" pointcut-ref="my"/>
<aop:advisor advice-ref="after" pointcut-ref="my"/>
</aop:config>
</beans>
log4j.properties:
log4j.rootCategory=info
log4j.logger.com.bjsxt.mapper=debug, CONSOLE
log4j.logger.com.bjsxt.advice=debug, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=- %c-%d-%m%n
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=- %c-%d-%m%n
WebContent:
login.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<form action="us" method="get">
使用者名稱:<input type="text" name="uname" value=""/><br />
密碼:<input type="password" name="pwd"/><br />
<input type="submit" value="提交" />
</form>
</body>
</html>
WEB-INF:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<!--配置Spring配置檔案路徑 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationcontext.xml</param-value>
</context-param>
<!--配置監聽器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
原始碼地址:
連結:https://pan.baidu.com/s/1n31EHGehJi8TqvImoJM2bw 密碼:gl6b
代理模式
其他連結
https://blog.csdn.net/cckevincyh/article/details/54962920
https://blog.csdn.net/u013126379/article/details/52121096
代理設計模式:
靜態代理設計模式:
真實類:要進行功能擴充套件的類
代理類:進行功能擴充套件的類
介面:真實類和代理類都要實現
代理流程:
代理類和真實類必須實現同一個介面
在代理類中呼叫真實類的方法,並完成功能擴充套件
修改呼叫方法為呼叫代理類
缺陷:
代理類又程式設計師自己編寫。
優點:
擴充套件真實類的功能
讓真實類的方法功能更加明確。
保護真實物件
動態代理設計模式:
特點:
動態生成代理物件。
JDK動態代理: 基於 介面
第一步:建立一個實現InvocationHandler介面的java類
並實現invoke方法
引數:
Object arg0:表示動態產生的代理物件
Method arg1:表示真實方法的Method物件
Object[] arg2:表示接收的實參
注意:
寫的是功能擴充套件程式碼。
第二步:
使用Proxy物件動態建立代理物件:
Proxy.newProxyInstance(TestBoss.class.getClassLoader(),new Class[]{Gongneng.class},new TestJdk());
使用返回值呼叫介面方法完成業務處理即可
注意:
該方法返回的是代理物件。
特點:
動態的產生代理物件
基於介面的,代理物件和真實物件需要實現相同的介面
不用匯入jar包
基於反射,效率低下
cglib動態代理 :基於繼承
第一步:
建立一個實現了MethodInterceptor介面的java類
實現介面方法:
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("你預約了嗎?");
arg1.invoke(new Boss(), arg2);
System.out.println("記錄吃飯記錄");
return null;
}
Object arg0, 代理物件
Method arg1, 真實方法物件
Object[] arg2, 引數
MethodProxy arg3 代理方法物件
第二步:動態獲取代理物件
Enhancer en=new Enhancer();
en.setSuperclass(Boss.class);//宣告要繼承的實現類
en.setCallback(new TestCglib());
Boss b2=(Boss)en.create();
b2.eat();
第三步:使用代理物件完成功能處理
特點:
基於繼承的,效率較高
需要匯入jar包
小結
Spring Aop概念學習
Schema-based方式
基於AspectJ方式
使用註解(基於AspectJ)
小案例
代理模式
相關文章
- 設計模式之面向切面程式設計AOP設計模式程式設計
- Spring之AOP面向切面程式設計Spring程式設計
- Spring AOP——Spring 中面向切面程式設計Spring程式設計
- AOP(面向切面程式設計)程式設計
- AOP 面向切面程式設計程式設計
- Spring AOP(面向切面程式設計)是什麼?Spring程式設計
- AOP--面向切面程式設計程式設計
- Spring 面向切面程式設計AOP 詳細講解Spring程式設計
- 手寫Spring---AOP面向切面程式設計(4)Spring程式設計
- 手寫Spring---AOP面向切面程式設計(3)Spring程式設計
- 前端js面向切面程式設計(AOP)前端JS程式設計
- Spring Boot實戰系列(3)AOP面向切面程式設計Spring Boot程式設計
- 前端解讀面向切面程式設計(AOP)前端程式設計
- 01.AOP(AspectOrientatedProgramming面向切面程式設計)程式設計
- aop面向切面程式設計的實現程式設計
- Java中的面向切面程式設計(AOP)Java程式設計
- JS實現AOP 面向切面程式設計 (裝飾者模式)JS程式設計模式
- .NET Core 實現動態代理做AOP(面向切面程式設計)程式設計
- 四、Spring-面向切面程式設計Spring程式設計
- Spring 面向方面程式設計 AOPSpring程式設計
- Spring框架系列(4) - 深入淺出Spring核心之面向切面程式設計(AOP)Spring框架程式設計
- 程式設計思想 面向切面程式設計程式設計
- 面向切面程式設計 ( Aspect Oriented Programming with Spring )程式設計Spring
- JAVA_動態代理AOP切面程式設計Java程式設計
- Spring AOP:面向切面程式設計的核心概念與實際應用Spring程式設計
- Spring理論基礎-面向切面程式設計Spring程式設計
- Spring系列:基於Spring-AOP和Spring-Aspects實現AOP切面程式設計Spring程式設計
- 面向切面程式設計和依賴注入程式設計依賴注入
- Spring 面向切面AOPSpring
- React Native面向切面程式設計React Native程式設計
- Spring Boot中面向方面程式設計 (AOP)教程Spring Boot程式設計
- JAVA-Spring AOP基礎 - 代理設計模式JavaSpring設計模式
- 從原始碼入手,一文帶你讀懂Spring AOP面向切面程式設計原始碼Spring程式設計
- Util應用框架基礎(三) - 面向切面程式設計(AspectCore AOP)框架程式設計
- Spring-AOP(面向切面)Spring
- Spring之切面程式設計Spring程式設計
- 基於SpringBoot AOP面向切面程式設計實現Redis分散式鎖Spring Boot程式設計Redis分散式
- (系列七).net8 Aop切面程式設計程式設計