8.AOP全自动
CGLIB字节码增强
l没有接口,只有实现类。
采用字节码增强框架 cglib,在运行时 创建目标类的子类,从而对目标类进行增强。
导入jar包:
自己导包(了解):
核心:hibernate-distribution-3.6.10.Final\lib\bytecode\cglib\cglib-2.2.jar
依赖:struts-2.3.15.3\apps\struts2-blank\WEB-INF\lib\asm-3.3.jar
spring-core..jar 已经整合以上两个内容

目标类
UserServiceImpl.java
package com.jd.proxy.cglib;
public class UserServiceImpl {
public void addUser() {
System.out.println("a_proxy.b_cglib addUser");
}
public void updateUser() {
System.out.println("a_proxy.b_cglib updateUser");
}
public void deleteUser() {
System.out.println("a_proxy.b_cglib deleteUser");
}
}
切面类
MyAspect
package com.jd.proxy.cglib;
public class MyAspect {
public void before(){
System.out.println("鸡首2");
}
public void after(){
System.out.println("牛后2");
}
}
工厂类
MyBeanFactory.java
package com.jd.proxy.cglib; import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /**
* @author weihu
* @date 2018/8/16/016 23:48
*/
public class MyBeanFactory { public static UserServiceImpl createService() {
//1.目标类
UserServiceImpl userService = new UserServiceImpl();
//2.切面类
MyAspect myAspect = new MyAspect();
// 3.代理类 ,采用cglib,底层创建目标类的子类
//3.1 核心类
Enhancer enhancer = new Enhancer();
//3.2 确定父类
enhancer.setSuperclass(userService.getClass());
/* 3.3 设置回调函数 , MethodInterceptor接口 等效 jdk InvocationHandler接口
* intercept() 等效 jdk invoke()
* 参数1、参数2、参数3:以invoke一样
* 参数4:methodProxy 方法的代理
*
*
*/
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//前
myAspect.before(); //执行目标类的方法
Object obj = method.invoke(userService, objects);
// * 执行代理类的父类 ,执行目标类 (目标类和代理类 父子关系)
// methodProxy.invokeSuper(o,objects); //后
myAspect.after();
return obj;
}
});
UserServiceImpl proxService = (UserServiceImpl) enhancer.create();
return proxService;
}
}
测试
TestCglib.java
package com.jd.proxy.cglib; import org.junit.Test; /**
* @author weihu
* @date 2018/8/16/016 23:55
*/
public class TestCglib { @Test
public void testCglib(){
UserServiceImpl service = MyBeanFactory.createService();
service.addUser();
service.updateUser();
service.deleteUser();
}
}
AOP联盟通知类型
l AOP联盟为通知Advice定义了org.aopalliance.aop.Advice l Spring按照通知Advice在目标类方法的连接点位置,可以分为5类 前置通知 org.springframework.aop.MethodBeforeAdvice
在目标方法执行前实施增强
后置通知 org.springframework.aop.AfterReturningAdvice
在目标方法执行后实施增强
环绕通知 org.aopalliance.intercept.MethodInterceptor
在目标方法执行前后实施增强
异常抛出通知 org.springframework.aop.ThrowsAdvice
在方法抛出异常后实施增强
引介通知 org.springframework.aop.IntroductionInterceptor
在目标类中添加一些新的方法和属性
环绕通知,必须手动执行目标方法 try{ //前置通知 //执行目标方法 //后置通知 } catch(){ //抛出异常通知 }
spring编写代理:半自动
让spring 创建代理对象,从spring容器中手动的获取代理对象。
导入jar包:
核心:4+1
AOP:AOP联盟(规范)、spring-aop (实现)

目标类
UserService.java
package com.jd.proxy.factorybean;
public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
切面类
MyAspect.java
package com.jd.proxy.factorybean; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; /**
* 切面类中确定通知,需要实现不同接口,接口就是规范,从而就确定方法名称。
* 采用“环绕通知” MethodInterceptor
*/
public class MyAspect implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("前"); //手动执行目标方法
Object obj = methodInvocation.proceed(); System.out.println("后");
return obj;
}
}
UserServiceImpl.java
package com.jd.proxy.factorybean;
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("b_factory_bean addUser");
}
@Override
public void updateUser() {
System.out.println("b_factory_bean updateUser");
}
@Override
public void deleteUser() {
System.out.println("b_factory_bean deleteUser");
}
}
spring配置
beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 创建目标类 -->
<bean id="userServiceId" class="com.jd.proxy.factorybean.UserServiceImpl"></bean>
<!-- 创建切面类 -->
<bean id="myAspectId" class="com.jd.proxy.factorybean.MyAspect"></bean> <!-- 创建代理类
* 使用工厂bean FactoryBean ,底层调用 getObject() 返回特殊bean
* ProxyFactoryBean 用于创建代理工厂bean,生成特殊代理对象
interfaces : 确定接口们
通过<array>可以设置多个值
只有一个值时,value=""
target : 确定目标类
interceptorNames : 通知 切面类的名称,类型String[],如果设置一个值 value=""
optimize :强制使用cglib
<property name="optimize" value="true"></property>
底层机制
如果目标类有接口,采用jdk动态代理
如果没有接口,采用cglib 字节码增强
如果声明 optimize = true ,无论是否有接口,都采用cglib -->
<bean id="proxyServiceId" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="com.jd.proxy.factorybean.UserService"></property>
<property name="target" ref="userServiceId"></property>
<property name="interceptorNames" value="myAspectId"></property>
</bean>
</beans>
测试
TestFactoryBean.java
package com.jd.proxy.factorybean; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* @author weihu
* @date 2018/8/18/018 18:11
*/
public class TestFactoryBean { @Test
public void testAop(){
String xmlPath="com/jd/proxy/factorybean/beans.xml"; //获得代理类
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService = (UserService) applicationContext.getBean("proxyServiceId");
userService.addUser();
userService.updateUser();
userService.deleteUser();
}
}
spring aop编程:全自动【掌握】
从spring容器获得目标类,如果配置aop,spring将自动生成代理。
要确定目标类,aspectj 切入点表达式,导入jar包
spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE

spring配置
beans.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="userServiceId" class="com.jd.proxy.aop.UserServiceImpl"></bean>
<!-- 创建切面类(通知) -->
<bean id="myAspectId" class="com.jd.proxy.aop.MyAspect"></bean>
<!-- aop编程
3.1 导入命名空间
3.2 使用 <aop:config>进行配置
proxy-target-class="true" 声明时使用cglib代理
<aop:pointcut> 切入点 ,从目标对象获得具体方法
<aop:advisor> 特殊的切面,只有一个通知 和 一个切入点
advice-ref 通知引用
pointcut-ref 切入点引用
3.3 切入点表达式
execution(* com.itheima.c_spring_aop.*.*(..))
选择方法 返回值任意 包 类名任意 方法名任意 参数任意 -->
<aop:config proxy-target-class="true">
<aop:pointcut expression="execution(* com.itheima.c_spring_aop.*.*(..))" id="myPointCut"/>
<aop:advisor advice-ref="myAspectId" pointcut-ref="myPointCut"/>
</aop:config>
</beans>
MyAspect.java
package com.jd.proxy.aop; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; /**
* 切面类中确定通知,需要实现不同接口,接口就是规范,从而就确定方法名称。
* * 采用“环绕通知” MethodInterceptor
*
*/
public class MyAspect implements MethodInterceptor { @Override
public Object invoke(MethodInvocation mi) throws Throwable { System.out.println("前4"); //手动执行目标方法
Object obj = mi.proceed(); System.out.println("后4");
return obj;
}
}
UserService.java
package com.jd.proxy.aop;
public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
UserServiceImpl.java
package com.jd.proxy.aop;
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("c_spring_aop addUser");
}
@Override
public void updateUser() {
System.out.println("c_spring_aop updateUser");
}
@Override
public void deleteUser() {
System.out.println("c_spring_aop deleteUser");
}
}
TestSpringAOP.java
package com.jd.proxy.aop; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* @author weihu
* @date 2018/8/18/018 18:21
*/
public class TestSpringAOP { @Test
public void testAop(){
String xmlPath="com/jd/proxy/aop/beans.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath); //获得目标类
UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser();
userService.updateUser();
userService.deleteUser();
}
}
8.AOP全自动的更多相关文章
- Spring全自动AOP和项目加入jar包
一.jar可以引进项目中,复制到路下后,要add as library,加载到工作空间中才能引入: 也jar包放在硬盘的项目目录外面,可以多个项目引入共用: 二.xml配置 1.aop全自动配置 2. ...
- Spring框架的基本使用(AOP部分)
AOP,Aspect Oriented Programming,意为面向切面编程,是通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP采取横向抽取机制,取代了传统纵向继承体系重复 ...
- Spring常用配置
----------------------------------------------------------------------------------------------[版权申明: ...
- AOP 手动,半自动,全自动
dao层 package com.yaorange.dao; public interface StudentDao { public void saveStudent(); public void ...
- spring的aop编程(半自动、全自动)
1.spring的半自动代理(从spring中获取代理对象) (1)spring中的通知类型 spring中aop的通知类型有五种: 前置:在目标方法执行前实施加强 后置:在目标方法执行后实施加强 环 ...
- spring(二) AOP之AspectJ框架的使用
前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...
- Spring框架-AOP详细学习[转载]
参考博客:https://blog.csdn.net/qq_22583741/article/details/79589910#4-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85% ...
- spring学习(二) ———— AOP之AspectJ框架的使用
前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...
- AOP切面编程
1.JDK动态代理方式实现 public static UserService createService(){ //目标类 final UserService userService = new U ...
随机推荐
- mac 安装软件
一.安装spark 1.官网下载最新tar文件 2.解压 3.安装java开发环境 3.1.安装下载java 8 https://www.oracle.com/technetwork/java/ja ...
- gdb 使用
2018年7月27日21:05:16 —— 多进程调试 1.follow_fork_mode 作用:在fork之后跟随父进程还是子进程 可以使用 show follow_fork_mode查看再for ...
- leetcode104
/** * Definition for a binary tree node. * public class TreeNode { * public int val; * public TreeNo ...
- 试了下阿里云的OPEN Api
逐渐理解open api的意义,试了下阿里云的续费接口,续费一个月 package com.test; /** * @author * @date 2018/12/05 */ import com.a ...
- Android Studio2.0 教程从入门到精通Windows版 - 入门篇
http://www.open-open.com/lib/view/open1468121363300.html 本文转自:深度开源(open-open.com)原文标题:Android Studio ...
- dto vo
不过符合规矩的做法是DTO里可以放各种List<VO>,而VO和entity就是一一对应的关系,vo里不能放entity,entity里也不能放vo,vo和entity只存放和数据库完全相 ...
- html2canvas
最近公司有个需求,实现html 页面元素转为png图像,这边用了html2canvas来实现.,这里记录一下,避免以后忘了~~ 官网链接: http://html2canvas.hertzen.com ...
- m文件转换c代码
parametet.mclc; clear; load('src.mat') CZT_N = ; CZT_M = ; CZT_W = exp(-j*(*pi/)); CZT_A = exp(j**pi ...
- 43 【redis cluster】
有两篇文章不错,可以看下: 1,初步理解redis cluster:https://blog.csdn.net/dc_726/article/details/48552531 2,仔细理解redis ...
- Git常用命令及场景
Git命令推送到远程分支 1.登录GitHub创建一个远程仓库. https://github.com 2.git init 本地创建一个目录,并初始化一个git仓库. 3.git add 添加文件到 ...