AOP的实现有三种方式:

l         aop底层将采用代理机制进行实现。

l         接口 + 实现类 :spring采用 jdk 的动态代理Proxy。

l         实现类:spring 采用 cglib字节码增强。

一.手工方式

1.JDK动态代理

JDK动态代理 对“装饰者”设计模式 简化。使用前提:必须有接口

1.目标类:接口 + 实现类

2.切面类:用于存通知 MyAspect

3.工厂类:编写工厂生成代理

4.测试

1.目标类

UserService.java

package com.zk.a_jdk;

public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}

UserServiceImpl.java

package com.zk.a_jdk;

public class UserServiceImpl implements UserService{

	@Override
public void addUser() {
// TODO Auto-generated method stub
System.out.println("proxy addUser");
} @Override
public void updateUser() {
// TODO Auto-generated method stub
System.out.println("proxy updateUser");
} @Override
public void deleteUser() {
// TODO Auto-generated method stub
System.out.println("proxy deleteUser");
} }

2.切面类

MyAspect.java

package com.zk.a_jdk;

public class MyAspect {

	public void before(){
System.out.println("鸡头");
} public void after(){
System.out.println("牛后");
}
}

3.工厂

package com.zk.a_jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class MyBeanFactory {
//手工代理
public static UserService createService(){
//1.目标类
final UserService userservice=new UserServiceImpl();
//2.切面类
final MyAspect myAspect=new MyAspect();
//3.代理类:将目标类(切入点)和切面类(通知)结合-->切面
//Proxy.newProxyInstance
/*
* 参数一:loader类加载器,动态代理类,运行时创建,任何类都需要类加载器将其加载至内存。
* 一般情况下:当前类,class.getClassLoader();
* 目标类实例:getClass().get...
* 参数二:interfaces,代理类需要实现的所有接口
* 方式一:目标类实例.getClass().getInterfaces();注意:只能获得自己的接口,获得不到父元素的接口
* 方式二:new Class[]{UserService.class}
* 例如:jdbc驱动
* 参数三:InvocationHandler 处理类,接口,必须进行实现类,一般采用匿名内部类
* 提供invoke方法,代理类每一个方法执行时,都将去调用invoke
* 参数三.1.Object proxy代理对象
* 参数三.2.Method method 代理对象当前方法的描述对象(反射)
* 执行方法方法名:method.getName();
* 执行方法:method.invoke(对象,实际参数)
* 参数三.3 Object[] args 方法实际参数
*/
UserService proxyService=(UserService)Proxy.newProxyInstance
(MyBeanFactory.class.getClassLoader(),
userservice.getClass().getInterfaces(), new InvocationHandler(){ @Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// TODO Auto-generated method stub //前执行
myAspect.before();
//执行目标类的方法
Object obj=method.invoke(userservice, args); //后执行
myAspect.after(); return null;
}
});
return proxyService;
}
}

4.测试类

package com.zk.a_jdk;

import org.junit.Test;

public class TestJDK {

	@Test
public void test(){
UserService userservice=MyBeanFactory.createService();
userservice.addUser();
userservice.deleteUser();
userservice.updateUser();
}
}

运行效果:

2.  CGLIB字节码增强

l         没有接口,只有实现类。

l         采用字节码增强框架 cglib,在运行时 创建目标类的子类,从而对目标类进行增强。

l         导入jar包:

1.目标类

UserService.java

package com.zk.a_jdk;

public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}

UserServiceImpl.java

package com.zk.a_jdk;

public class UserServiceImpl implements UserService{

	@Override
public void addUser() {
// TODO Auto-generated method stub
System.out.println("proxy addUser");
} @Override
public void updateUser() {
// TODO Auto-generated method stub
System.out.println("proxy updateUser");
} @Override
public void deleteUser() {
// TODO Auto-generated method stub
System.out.println("proxy deleteUser");
} }

2.切面类

MyAspect.java

package com.zk.a_jdk;

public class MyAspect {

	public void before(){
System.out.println("鸡头");
} public void after(){
System.out.println("牛后");
}
}

3.MyBeanFactory.java工厂类

package com.zk.b_cglib;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; public class MyBeanFactory {
//手工代理
public static UserService createService(){
//1.目标类
final UserServiceImpl userservice=new UserServiceImpl();
//2.切面类
final MyAspect myAspect=new MyAspect();
/*3.代理类
* 采用字节码增强框架-cglib,程序运行时创建目标类的子类,从而对目标类进行增强
* 导入jar包
* intercept等效于jdk中invoke方法
* 参数一二三 与invoke相同
* 参数四方法的代理
*/
Enhancer enhance=new Enhancer();
//确定父类
enhance.setSuperclass(userservice.getClass());
enhance.setCallback(new MethodInterceptor(){
//设置回调函数,MethodInterceptor接口等效 jdk InvocationHandler接口
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodproxy) throws Throwable {
// TODO Auto-generated method stub
//前before
myAspect.before();
//执行目标类的方法
Object obj=method.invoke(userservice, args);
//执行代理类的父类
methodproxy.invokeSuper(proxy, args);
//后after
myAspect.after();
return null;
} });
//创建代理
UserServiceImpl proxyservice=(UserServiceImpl) enhance.create();
return proxyservice;
}
}

4.TestCglib.java测试

package com.zk.b_cglib;

import org.junit.Test;

public class Testcglib {

	@Test
public void test(){
UserService userservice=MyBeanFactory.createService();
userservice.addUser();
userservice.deleteUser();
userservice.updateUser();
}
}

运行效果图:

二.半自动方式

让spring 创建代理对象,从spring容器中手动的获取代理对象。

导入jar包:

AOP:AOP联盟(规范)、spring-aop (实现)

1.目标类

UserService.java

public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}

UserServiceImpl.java

package com.zk.springAop;

public class UserServiceImpl implements UserService{

	@Override
public void addUser() {
// TODO Auto-generated method stub
System.out.println("addUser");
} @Override
public void updateUser() {
// TODO Auto-generated method stub
System.out.println("updateUser");
} @Override
public void deleteUser() {
// TODO Auto-generated method stub
System.out.println("deleteUser");
} }

2.切面类

/**
* 切面类中确定通知,需要实现不同接口,接口就是规范,从而就确定方法名称。
* * 采用“环绕通知” MethodInterceptor
*
*/
public class MyAspect implements MethodInterceptor { @Override
public Object invoke(MethodInvocation mi) throws Throwable { System.out.println("前3"); //手动执行目标方法
Object obj = mi.proceed(); System.out.println("后3");
return obj;
}
}

3.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<!-- 创建目标类 -->
<bean id="userserviceid" class="com.zk.factorybean.UserServiceImpl"></bean> <!-- 创建切面类 -->
<bean id="aspectid" class="com.zk.factorybean.MyAspect"></bean> <!-- 创建代理类
使用工厂bean factorybean,底层调用getObject(), 返回特殊bean
ProxyBeanFactory用于创建代理工厂bean,生成特殊代理对象
interface确定接口
通过Array确定多个值
只有一个值时,value=""
target确定目标类
interceptorNames:通知切面类名称,类型String[],如果设置一个值, value=""
optimize:强制使用cglib
<property name="optimized value="true"></property>
底层机制:
如果目标类有接口,采用jdk代理
如果没有接口,采用cglib代理
如果声明式optimize=true,都使用cglib
-->
<bean id="proxyServiceid" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="com.zk.factorybean.UserService"></property>
<property name="target" ref="userserviceid"></property>
<property name="interceptorNames" value="aspectid"></property>
</bean>
</beans>

  

4.Testfactorybean.java

package com.zk.factorybean;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Testfactorybean { @Test
public void test(){
String path="com/zk/factorybean/ApplicationContext.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(path);
UserService userservice=(UserService) ac.getBean("proxyServiceid");
userservice.addUser();
userservice.deleteUser();
userservice.updateUser();
}
}

  

运行效果:

三.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

1.目标类

UserService.java

public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}

UserServiceImpl.java

package com.zk.springAop;

public class UserServiceImpl implements UserService{

	@Override
public void addUser() {
// TODO Auto-generated method stub
System.out.println("addUser");
} @Override
public void updateUser() {
// TODO Auto-generated method stub
System.out.println("updateUser");
} @Override
public void deleteUser() {
// TODO Auto-generated method stub
System.out.println("deleteUser");
} }

2.切面类

/**
* 切面类中确定通知,需要实现不同接口,接口就是规范,从而就确定方法名称。
* * 采用“环绕通知” MethodInterceptor
*
*/
public class MyAspect implements MethodInterceptor { @Override
public Object invoke(MethodInvocation mi) throws Throwable { System.out.println("前3"); //手动执行目标方法
Object obj = mi.proceed(); System.out.println("后3");
return obj;
}
}

3.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!-- 创建目标类 -->
<bean id="userserviceid" class="com.zk.springAop.UserServiceImpl"></bean> <!-- 创建切面类 -->
<bean id="aspectid" class="com.zk.springAop.MyAspect"></bean> <!-- Aop编程
1.导入命名空间
2.使用<aop:config>进行配置
proxy-target-class="true"声明是使用cglib代理
<aop:pointcut>:切入点,从目标对象上获取具体的方法
<aop:advisor>特殊的切面,只有一个通知和一个切入点
advise-ref 通知引用
pointcut-ref 切入点引用
advisor通知
3.切入点表达式
execution(* com.zk.springAop.*.*(..))
选择方法 *表示返回值任意 包 类名任意. 方法名任意 . 参数任意 .
-->
<aop:config>
<aop:pointcut expression="execution(* com.zk.springAop.*.*(..))" id="myPointCut"/>
<aop:advisor advice-ref="aspectid" pointcut-ref="myPointCut"/>
</aop:config>
</beans>

  

Spring AOP编程(二)-AOP实现的三种方式的更多相关文章

  1. Spring的依赖注入(DI)三种方式

    Spring依赖注入(DI)的三种方式,分别为: 1.  接口注入 2.  Setter方法注入 3.  构造方法注入 下面介绍一下这三种依赖注入在Spring中是怎么样实现的. 首先我们需要以下几个 ...

  2. spring学习(03)之bean实例化的三种方式

    bean实体例化的三种方式 在spring中有三中实例化bean的方式: 一.使用构造器实例化:(通常使用的一个方法,重点) 二.使用静态工厂方法实例化: 三.使用实例化工厂方法实例化 第一种.使用构 ...

  3. Spring bean管理器 bean实例化的三种方式

    bean实例化的三种方式实现 第一种:使用类的无参数构造方法创建(常用 重要) 第一种实例化方式最常用,实例化类时会通过调用无参构造方法创建.示例代码如下: package spring.com.Us ...

  4. Struts2(二)action的三种方式

    一.普通java类 package com.pb.web.action; /* * 创建普通的java类 */ public class HelloAction1 { public String ex ...

  5. Spring管理的bean初始化方法的三种方式,以及@PostConstruct不起作用的原因

    1:Spring 容器中的 Bean 是有生命周期的,spring 允许 Bean 在初始化完成后以及销毁前执行特定的操作.下面是常用的三种指定特定操作的方法: 通过实现InitializingBea ...

  6. Spring:Spring-IOC实例化bean的常用三种方式

    Spring容器提供了三种对bean的实例化方式: 1)构造器实例化 public class Demo { private String name; //getter和setter方法略 } < ...

  7. 【spring】 SpringMVC返回json数据的三种方式

    配置方法一 **1.导入第三方的jackson包,jackson-mapper-asl-1.9.7.jar和jackson-core-asl-1.9.7.jar. 2.spring配置文件添加** & ...

  8. Spring学习(五)-----注入bean属性的三种方式( 1: 正常的方式 2: 快捷方式 3: “p” 模式)

    在Spring中,有三种方式注入值到 bean 属性. 正常的方式 快捷方式 “p” 模式 看到一个简单的Java类,它包含两个属性 - name 和 type.稍后将使用Spring注入值到这个 b ...

  9. SSH深度历险记(八) 剖析SSH核心原则+Spring依赖注入的三种方式

           于java发育.一类程序猿必须依靠类的其他方法,它是通常new依赖类的方法,然后调用类的实例,这样的发展问题new良好的班统一管理的例子.spring提出了依赖注入的思想,即依赖类不由程 ...

随机推荐

  1. 《深入理解java虚拟机》读书笔记六——第七章

    第七章 虚拟机类加载机制 1.类加载的时机 虚拟机的类加载机制: 虚拟机把描述类的数据从class文件中加载到内存,并对数据进行校验.转换解析和初始化,最终形成了可以被虚拟机直接使用的Java类型,这 ...

  2. C# SDO_GEOMETRY

    OracleParameter endGeometry = cmd.CreateParameter(); endGeometry.OracleDbType = OracleDbType.Object; ...

  3. .net Core 配置Centos守护进程Supervisor

    声明: 博客引用来源:https://blog.csdn.net/qq_37997978/article/details/83311177建议看原版,更为详细 介绍: Supervisor( http ...

  4. 刷题76. Minimum Window Substring

    一.题目说明 题目76. Minimum Window Substring,求字符串S中最小连续字符串,包括字符串T中的所有字符,复杂度要求是O(n).难度是Hard! 二.我的解答 先说我的思路: ...

  5. 0005 修改Django工程名

    写框架非常耗时间,把框架写好以后,经测试稳定的框架,需要保存下来,以后有工程需要,直接更改工程名即可. 01 右键点击工程名,点击Refactor/Rename 02 选择更改工程名 03 关闭PyC ...

  6. OpenGL 编程指南 (2)

    1.OpenGL对共享的边有严格的规定:1)共享边上的像素因为同事被两者所覆盖,因此不可能不受到光照计算的影响: 2)共享边上的像素值,不可能受到多于一个三角形的光照计算的影响. 2.多边形存在正面与 ...

  7. testclass面试题

    http://www.testclass.net/interview/selenium/   seleniuim面试题 http://www.testclass.net/interview/inter ...

  8. 一个小时学会jQuery(转载)

    目录 一.jQuery简介与第一个jQuery程序 1.1.jQuery简介 1.2.jQuery特点 1.3.jQuery版本 1.4.获得jQuery库 1.5.第一个jQuery程序 二.jQu ...

  9. Python学习笔记9——异常处理

    处理异常 如果执行到程序中某处抛出了异常,程序就会被终止并退出.你可能会问,那有没有什么办法可以不终止程序,让其照样运行下去呢?答案当然是肯定的,这也就是我们所说的异常处理,通常使用 try 和 ex ...

  10. Ajax返回值一直获取不到啊

      原理: 同步异步的问题 Return 位置的问题     首先同步异步改为async : false,   Return 的值写在ajax外部  function submit_answer(){ ...