Spring中AOP的代理方式
静态代理类:
由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的
.class文件就已经存在了。
动态代理类 :在程序运行时,运用反射机制动态创建而成 。动态代理分为两种代理;
jdk代理和cglib的代理
jdk代理必须有一个接口用来实现,就是对目标对象生成代理,进行代理,然后就是返回目标对象的代理。Invoction
cglib和jdk代理的区别在与 他需要导入一个cglib.jar包,cglib是基于jdk封装而成的,主要的就是cglib相对灵活,因为jdk必须要实现接口
而cglib可以使接口也可以是类。
静态代理和动态代理
代理,应该就是在不破坏原有代码的基础上,对原有代码进行扩充。
一、静态代理
代理类与原类实现相同的接口。
不过静态代理会在代码里写死,对于需要在运行期生成的代码就无能为力了。
1.UserManager.java
package com; public interface UserManager { public void addUser(String username, String password); public void deleteUser(int id); public void modifyUser(int id, String username, String password); public String findUserByID(int id); } |
2.UserManagerImpl.java
package com; public class UserManagerImpl implements UserManager { public void addUser(String username, String password) { System.out.println("========UserManagerImpl.addUser()==================="); } public void deleteUser(int id) { System.out.println("========UserManagerImpl.deleteUser()==================="); } public String findUserByID(int id) { System.out.println("========UserManagerImpl.findUserByID()==================="); return "ok"; } public void modifyUser(int id, String username, String password) { System.out.println("========UserManagerImpl.modifyUser()==================="); } } |
3.UserManagerImplProxy.java(代理类)
package com; public class UserManagerImplProxy implements UserManager { private UserManager userManager; public UserManagerImplProxy(UserManager userManager) { this.userManager = userManager; } @Override public void addUser(String username, String password) { // TODO Auto-generated method stub checkSecurity(); userManager.addUser(username, password); } @Override public void deleteUser(int id) { // TODO Auto-generated method stub userManager.deleteUser(id); } @Override public String findUserByID(int id) { // TODO Auto-generated method stub return userManager.findUserByID(id); } @Override public void modifyUser(int id, String username, String password) { // TODO Auto-generated method stub userManager.modifyUser(id, username, password); } private void checkSecurity() { System.out.println("==============checkSecurity()=================="); } } |
4.Client.java(客户端)
package com; public class Client { public static void main(String[] args) { UserManager userManager = new UserManagerImplProxy(new UserManagerImpl()); userManager.addUser("Tom", "123"); } } |
二、动态代理
可以解决运行期执行的问题,动态代理没有必要事先将代码写死。
1.SecurityHandler.java
package com; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class SecurityHandler implements InvocationHandler { private Object targetObject; public Object newProxy(Object targetObject) { this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { checkSecurity(); //方法返回值 Object ret = null; try { //args是方法参数 ret = method.invoke(targetObject, args); } catch (RuntimeException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ret; } private void checkSecurity() { System.out.println("===============checkSecurity()==================="); } } |
2.Client.java
package com; public class Client { public static void main(String[] args) { SecurityHandler handler = new SecurityHandler(); UserManager userManager = (UserManager)handler.newProxy(new UserManagerImpl()); userManager.addUser("Tom", "123"); System.out.println(userManager.findUserByID(1)); } } |
动态代理的JDK代理和CGLib代理
JDK代理
这里我们学习一下代理模式,JDK的动态代理,以及以JDK为基础的springAOP实现
代理模式:类结构的模式,优点就是不需要更改原有类(被代理类)就能增强原有类(被代理类)的功能,缺点就是必须实现原有类(被代理类)的接口
JDK的动态代理:优点就是不必“复制”原有类(被代理类)接口实现类,缺点就是必须为每个被代理类实现几乎一样的方法
springAOP:优点就是采用springIOC,JDK动态代理等技术来实现AOP机制
我们展示一个类的几个方法,分别采用代理模式,JDK动态代理,springAOP机制来做些额外功能
这里定义一个接口,一个实现类
- package com.fruitking.proxy;
-
-
-
-
-
-
- public interface CarService {
-
-
-
-
- public void start();
-
-
-
-
-
- public int getLoadAmount();
-
-
-
-
-
-
- public String setDriver(String driver);
-
-
-
-
-
-
-
- public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException;
- }
package com.fruitking.proxy;
/**
* 汽车服务类接口
* @author fruitking
* @since 2010-02-23
*/
public interface CarService {
/**
* 启动汽车
*/
public void start();
/**
* 获得汽车搭载人数
* @return
*/
public int getLoadAmount();
/**
* 设置驾驶员
* @param driver
* @return
*/
public String setDriver(String driver);
/**
* 搭载货物
* @param goods
* @throws NullPointerException
* @throws IllegalArgumentException
*/
public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException;
}
- package com.fruitking.proxy;
-
-
-
-
-
-
- public class CarServiceImpl implements CarService{
-
-
-
-
- public void start(){
- System.out.println("start my car...");
- }
-
-
-
-
-
- public int getLoadAmount(){
- System.out.println("count the person amount in my car...");
- return 5;
- }
-
-
-
-
-
-
- public String setDriver(String driver){
- System.out.println("driver is:"+driver);
- if(driver==null||"".equals(driver)){
- return "There is not driver.";
- }else{
- return "The driver's name is " + driver + ".";
- }
- }
-
-
-
-
-
-
-
- public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{
- if(goods==null||"".equals(goods)){
- throw new NullPointerException("The argument goods is null.");
- }else if("tiger".equals(goods)){
- throw new IllegalArgumentException("The argument goods is invalid.");
- }
- System.out.println("load goods is:"+goods);
- }
- }
package com.fruitking.proxy;
/**
* 汽车服务类接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceImpl implements CarService{
/**
* 启动汽车
*/
public void start(){
System.out.println("start my car...");
}
/**
* 获得汽车搭载人数
* @return
*/
public int getLoadAmount(){
System.out.println("count the person amount in my car...");
return 5;
}
/**
* 设置驾驶员
* @param driver
* @return
*/
public String setDriver(String driver){
System.out.println("driver is:"+driver);
if(driver==null||"".equals(driver)){
return "There is not driver.";
}else{
return "The driver's name is " + driver + ".";
}
}
/**
* 搭载货物
* @param goods
* @throws NullPointerException
* @throws IllegalArgumentException
*/
public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{
if(goods==null||"".equals(goods)){
throw new NullPointerException("The argument goods is null.");
}else if("tiger".equals(goods)){
throw new IllegalArgumentException("The argument goods is invalid.");
}
System.out.println("load goods is:"+goods);
}
}
先来看看代理模式,定义一个代理类,然后调用代理类
- package com.fruitking.proxy.pattern;
-
- import com.fruitking.proxy.CarService;
-
-
-
-
-
-
- public class CarServiceProxy implements CarService {
-
- private CarService carServiceTarget;
-
-
-
-
-
-
- public CarServiceProxy(CarService carServiceTarget){
- this.carServiceTarget = carServiceTarget;
- }
-
-
-
-
- public void start(){
- System.out.println("before excute target object...");
- carServiceTarget.start();
- System.out.println("after excute target object...");
- }
-
-
-
-
-
- public int getLoadAmount(){
- System.out.println("before excute target object...");
- int amount = carServiceTarget.getLoadAmount();
- System.out.println("after excute target object...");
- return amount;
- }
-
-
-
-
-
-
- public String setDriver(String driver){
- System.out.println("before excute target object...");
- String resultObject = carServiceTarget.setDriver(driver);
- System.out.println("after excute target object...");
- return resultObject;
- }
-
-
-
-
-
-
-
- public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{
-
- }
- }
package com.fruitking.proxy.pattern;
import com.fruitking.proxy.CarService;
/**
* 汽车服务类接口的代理类实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceProxy implements CarService {
private CarService carServiceTarget;//被代理的目标类
/**
* 在构造函数中设置被代理的目标类
* 也可以使用set方法设置被代理的目标类
* @param carServiceTarget
*/
public CarServiceProxy(CarService carServiceTarget){
this.carServiceTarget = carServiceTarget;
}
/**
* 启动汽车
*/
public void start(){
System.out.println("before excute target object...");
carServiceTarget.start();
System.out.println("after excute target object...");
}
/**
* 获得汽车搭载人数
* @return
*/
public int getLoadAmount(){
System.out.println("before excute target object...");
int amount = carServiceTarget.getLoadAmount();
System.out.println("after excute target object...");
return amount;
}
/**
* 设置驾驶员
* @param driver
* @return
*/
public String setDriver(String driver){
System.out.println("before excute target object...");
String resultObject = carServiceTarget.setDriver(driver);
System.out.println("after excute target object...");
return resultObject;
}
/**
* 搭载货物
* @param goods
* @throws NullPointerException
* @throws IllegalArgumentException
*/
public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{
//这里不实现任何操作
}
}
- package com.fruitking.proxy.pattern;
-
- import com.fruitking.proxy.CarService;
- import com.fruitking.proxy.CarServiceImpl;
-
- public class TestProxyPattern {
-
-
-
-
-
- public static void main(String[] args) {
- CarService carServiceTarget = new CarServiceImpl();
- CarServiceProxy carServiceProxy = new CarServiceProxy(carServiceTarget);
-
-
-
-
-
- carServiceProxy.start();
- carServiceProxy.getLoadAmount();
- String driver = carServiceProxy.setDriver("fruitking");
- System.out.println(driver);
- }
- }
package com.fruitking.proxy.pattern;
import com.fruitking.proxy.CarService;
import com.fruitking.proxy.CarServiceImpl;
public class TestProxyPattern {
/**
* 代理模式中的调用
* @param args
*/
public static void main(String[] args) {
CarService carServiceTarget = new CarServiceImpl();
CarServiceProxy carServiceProxy = new CarServiceProxy(carServiceTarget);
//执行代理类的方法
//作用一:间接执行被代理类的方法,
//作用二:代理类可以在被代理类方法执行前后做一些额外操作
//总结:不更改原有类的功能和程序代码情况下,实现额外的功能能
//缺点:要为每个被代理类编写一个代理类,且需要实现相同接口的所有方法
carServiceProxy.start();
carServiceProxy.getLoadAmount();
String driver = carServiceProxy.setDriver("fruitking");
System.out.println(driver);
}
}
再来看看JDK动态代理
- package com.fruitking.proxy.jdkdproxy;
-
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
-
- import com.fruitking.proxy.CarService;
-
-
-
-
-
-
- public class CarServiceJDKDynamicProxy implements InvocationHandler {
-
- private CarService carServiceTarget;
-
-
-
-
-
-
- public CarServiceJDKDynamicProxy(CarService carServiceTarget){
- this.carServiceTarget = carServiceTarget;
- }
-
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- System.out.println("before excute target object...");
- Object object = method.invoke(this.carServiceTarget,args);
- System.out.println("after excute target object...");
- return object;
- }
- }
package com.fruitking.proxy.jdkdproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.fruitking.proxy.CarService;
/**
* java动态代理实现类
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceJDKDynamicProxy implements InvocationHandler {
private CarService carServiceTarget;//被代理的目标类
/**
* 在构造函数中设置被代理的目标类
* 也可以使用set方法设置被代理的目标类
* @param carServiceTarget
*/
public CarServiceJDKDynamicProxy(CarService carServiceTarget){
this.carServiceTarget = carServiceTarget;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before excute target object...");
Object object = method.invoke(this.carServiceTarget,args);
System.out.println("after excute target object...");
return object;
}
}
- package com.fruitking.proxy.jdkdproxy;
-
- import java.lang.reflect.Proxy;
-
- import com.fruitking.proxy.CarService;
- import com.fruitking.proxy.CarServiceImpl;
-
- public class TestJDKDynamicProxy {
-
-
-
-
-
- public static void main(String[] args) {
- CarService carServiceTarget = new CarServiceImpl();
- CarServiceJDKDynamicProxy carServiceJDKDynamicProxyTarget = new CarServiceJDKDynamicProxy(carServiceTarget);
- CarService carServiceProxy = (CarService)Proxy.newProxyInstance(carServiceTarget.getClass().getClassLoader(),new Class[]{CarService.class}, carServiceJDKDynamicProxyTarget);
-
-
-
-
-
- carServiceProxy.start();
- carServiceProxy.getLoadAmount();
- String driver = carServiceProxy.setDriver("fruitking");
- System.out.println(driver);
- }
-
- }
package com.fruitking.proxy.jdkdproxy;
import java.lang.reflect.Proxy;
import com.fruitking.proxy.CarService;
import com.fruitking.proxy.CarServiceImpl;
public class TestJDKDynamicProxy {
/**
* JDK中动态代理技术中的代理调用
* @param args
*/
public static void main(String[] args) {
CarService carServiceTarget = new CarServiceImpl();
CarServiceJDKDynamicProxy carServiceJDKDynamicProxyTarget = new CarServiceJDKDynamicProxy(carServiceTarget);
CarService carServiceProxy = (CarService)Proxy.newProxyInstance(carServiceTarget.getClass().getClassLoader(),new Class[]{CarService.class}, carServiceJDKDynamicProxyTarget);
//执行代理类的方法
//作用一:间接执行被代理类的方法,
//作用二:代理类可以在被代理类方法执行前后做一些额外操作
//总结:不更改原有类的功能和程序代码情况下,实现额外的功能能
//缺点:要为每个被代理类编写一个代理类,且具有相同的接口
carServiceProxy.start();
carServiceProxy.getLoadAmount();
String driver = carServiceProxy.setDriver("fruitking");
System.out.println(driver);
}
}
最后来看看spring的AOP机制的实现
- package com.fruitking.proxy.springaop;
-
- import java.lang.reflect.Method;
-
- import org.springframework.aop.MethodBeforeAdvice;
-
-
-
-
-
-
- public class CarServiceBeforeAdvice implements MethodBeforeAdvice{
-
- public void before(Method method, Object[] args, Object target)throws Throwable {
- System.out.println("before excute target object...");
- String methodName = method.getName();
- String targetClassName = target.getClass().getName();
- System.out.println(targetClassName+"."+methodName+"()");
- }
- }
package com.fruitking.proxy.springaop;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
/**
* 使用spring的AOP机制的事前通知接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceBeforeAdvice implements MethodBeforeAdvice{
public void before(Method method, Object[] args, Object target)throws Throwable {
System.out.println("before excute target object...");
String methodName = method.getName(); //得到方法名
String targetClassName = target.getClass().getName();//得到调用类名
System.out.println(targetClassName+"."+methodName+"()");
}
}
- package com.fruitking.proxy.springaop;
-
- import java.lang.reflect.Method;
-
- import org.springframework.aop.AfterReturningAdvice;
-
-
-
-
-
-
- public class CarServiceAfterAdvice implements AfterReturningAdvice {
-
- public void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable{
- String methodName = method.getName();
- String targetClassName = target.getClass().getName();
- System.out.println(targetClassName+"."+methodName+"()");
- System.out.println("after excute target object...");
- }
- }
package com.fruitking.proxy.springaop;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
/**
* 使用spring的AOP机制的事前通知接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceAfterAdvice implements AfterReturningAdvice {
public void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable{
String methodName = method.getName(); //得到方法名
String targetClassName = target.getClass().getName();//得到调用类名
System.out.println(targetClassName+"."+methodName+"()");
System.out.println("after excute target object...");
}
}
- package com.fruitking.proxy.springaop;
-
- import org.aopalliance.intercept.MethodInterceptor;
- import org.aopalliance.intercept.MethodInvocation;
-
-
-
-
-
-
- public class CarServiceAroundAdvice implements MethodInterceptor {
-
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.println("before around excute target object...");
- String methodName = invocation.getMethod().getName();
- String targetClassName = invocation.getClass().getName();
- System.out.println(targetClassName+"."+methodName+"()");
- Object result = invocation.proceed();
- System.out.println("after around excute target object...");
- return result;
- }
- }
package com.fruitking.proxy.springaop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* 使用spring的AOP机制的事前通知接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceAroundAdvice implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before around excute target object...");
String methodName = invocation.getMethod().getName(); //得到方法名
String targetClassName = invocation.getClass().getName();//得到调用类名
System.out.println(targetClassName+"."+methodName+"()");
Object result = invocation.proceed(); //调用横切点,即真实操作
System.out.println("after around excute target object...");
return result;
}
}
- package com.fruitking.proxy.springaop;
-
- import org.springframework.aop.ThrowsAdvice;
-
-
-
-
-
-
- public class CarServiceThrowsAdvice implements ThrowsAdvice {
-
- public void afterThrowing(NullPointerException e){
- System.out.print("not load anything goods!");
- }
-
- public void afterThrowing(IllegalArgumentException e){
- System.out.print("load a tiger,it's very much dangerous!");
- }
-
- }
package com.fruitking.proxy.springaop;
import org.springframework.aop.ThrowsAdvice;
/**
* 使用spring的AOP机制的事前通知接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(NullPointerException e){//可以定义多个方法,只要传入的参数是不同异常
System.out.print("not load anything goods!");
}
public void afterThrowing(IllegalArgumentException e){//可以定义多个方法,只要传入的参数是不同异常
System.out.print("load a tiger,it's very much dangerous!");
}
}
spring的配置文件,把这些使用IOC处理
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
- <beans>
-
- <bean id="carServiceTarget" class="com.fruitking.proxy.CarServiceImpl"/>
-
- <bean id="carServiceBeforeAdvice" class="com.fruitking.proxy.springaop.CarServiceBeforeAdvice"/>
-
- <bean id="carServiceAfterAdvice" class="com.fruitking.proxy.springaop.CarServiceAfterAdvice"/>
-
- <bean id="carServiceAroundAdvice" class="com.fruitking.proxy.springaop.CarServiceAroundAdvice"/>
-
- <bean id="carServiceThrowsAdvice" class="com.fruitking.proxy.springaop.CarServiceThrowsAdvice"/>
-
- <bean id="carService" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces" value="com.fruitking.proxy.CarService"/>
- <property name="target" ref="carServiceTarget"/>
- <property name="interceptorNames">
- <list>
- <value>carServiceBeforeAdvice</value>
- <value>carServiceAfterAdvice</value>
- <value>carServiceAroundAdvice</value>
- <value>carServiceThrowsAdvice</value>
- </list>
- </property>
- </bean>
-
- </beans>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="carServiceTarget" class="com.fruitking.proxy.CarServiceImpl"/>
<bean id="carServiceBeforeAdvice" class="com.fruitking.proxy.springaop.CarServiceBeforeAdvice"/>
<bean id="carServiceAfterAdvice" class="com.fruitking.proxy.springaop.CarServiceAfterAdvice"/>
<bean id="carServiceAroundAdvice" class="com.fruitking.proxy.springaop.CarServiceAroundAdvice"/>
<bean id="carServiceThrowsAdvice" class="com.fruitking.proxy.springaop.CarServiceThrowsAdvice"/>
<bean id="carService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.fruitking.proxy.CarService"/>
<property name="target" ref="carServiceTarget"/>
<property name="interceptorNames">
<list>
<value>carServiceBeforeAdvice</value>
<value>carServiceAfterAdvice</value>
<value>carServiceAroundAdvice</value>
<value>carServiceThrowsAdvice</value>
</list>
</property>
</bean>
</beans>
- package com.fruitking.proxy.springaop;
-
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- import com.fruitking.proxy.CarService;
-
- public class TestSpringAOP {
-
-
-
-
-
- public static void main(String[] args) {
- ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
- CarService carService = (CarService) ctx.getBean("carService");
- carService.start();
- carService.getLoadAmount();
- String driver = carService.setDriver("fruitking");
- System.out.println(driver);
- System.out.println("------------------------------");
- carService.loadGoods("Miss Mary");
- System.out.println("------------------------------");
- try{
- carService.loadGoods(null);
- }catch(NullPointerException e){
- e.printStackTrace();
- }
- System.out.println("------------------------------");
- try{
- carService.loadGoods("tiger");
- }catch(IllegalArgumentException e){
- e.printStackTrace();
- }
- }
-
- }
CGlib代理
- package com.bjsxt.spring;
-
- public class UserManagerImpl {
-
-
- public void addUser(String name, String password) {
- System.out.println("UserManagerImpl.addUser() -- name: " + name);
- }
-
- public void delUser(int id) {
- System.out.println("UserManagerImpl.delUser() -- id: " + id);
- }
-
- public void modifyUser(int id, String name, String password) {
- System.out.println("UserManagerImpl.modifyUser() -- id: " + id);
- }
-
- }
package com.bjsxt.spring; public class UserManagerImpl { public void addUser(String name, String password) { System.out.println("UserManagerImpl.addUser() -- name: " + name); } public void delUser(int id) { System.out.println("UserManagerImpl.delUser() -- id: " + id); } public void modifyUser(int id, String name, String password) { System.out.println("UserManagerImpl.modifyUser() -- id: " + id); } }
- package com.bjsxt.spring;
-
- import org.aspectj.lang.JoinPoint;
-
- public class MySecurityManagerImpl {
-
- public void checkSecurity(JoinPoint joinPoint) {
- Object[] args = joinPoint.getArgs();
- if (args != null) {
- for (int i = 0; i < args.length; i++) {
- System.out.println(args[i]);
- }
- if ("张三".equals(args[0])) {
- System.out.println("你没有权限访问");
- }
- }
- //...
- //...
- //System.out.println("进行安全检查!!");
- }
- }
package com.bjsxt.spring; import org.aspectj.lang.JoinPoint; public class MySecurityManagerImpl { public void checkSecurity(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); if (args != null) { for (int i = 0; i < args.length; i++) { System.out.println(args[i]); } if ("张三".equals(args[0])) { System.out.println("你没有权限访问");
}
2.看看这次spring配置文件是如何配置的.
- <?xml version="1.0" encoding="UTF-8"?>
-
- <!--
- - Application context definition for JPetStore's business layer.
- - Contains bean references to the transaction manager and to the DAOs in
- - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
- -->
- <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 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
-
- <bean id="userManager" class="com.bjsxt.spring.UserManagerImpl"/>
-
- <bean id="mySecurityManager" class="com.bjsxt.spring.MySecurityManagerImpl"/>
-
- <aop:config>
- <aop:pointcut id="allAddMethod" expression="execution(* add*(..))"/>
- <aop:aspect id="securityAspect" ref="mySecurityManager">
- <aop:before pointcut-ref="allAddMethod" method="checkSecurity"/>
- </aop:aspect>
- </aop:config>
-
- </beans>
<?xml version="1.0" encoding="UTF-8"?> <!-- - Application context definition for JPetStore's business layer. - Contains bean references to the transaction manager and to the DAOs in - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation"). --> <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 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean id="userManager" class="com.bjsxt.spring.UserManagerImpl"/> <bean id="mySecurityManager" class="com.bjsxt.spring.MySecurityManagerImpl"/> <aop:config> <aop:pointcut id="allAddMethod" expression="execution(* add*(..))"/> <aop:aspect id="securityAspect" ref="mySecurityManager"> <aop:before pointcut-ref="allAddMethod" method="checkSecurity"/> </aop:aspect> </aop:config> </beans>
3.写测试类
- package com.bjsxt.spring;
-
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- import junit.framework.TestCase;
-
-
- public class TestAop extends TestCase {
-
- public void testAop1() {
- //读取配置文件,获取BeanFactory
- BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext-beans.xml");
- UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager");
- userManager.addUser("张三", "123");
- // userManager.delUser(1);
- // userManager.modifyUser(1, "李四", "abc");
- }
- }
package com.bjsxt.spring; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationC<wbr>ontext; import junit.framework.TestCase; public class TestAop extends TestCase { public void testAop1() { //读取配置文件,获取BeanFactory BeanFactory factory = new ClassPathXmlApplicationC<wbr>ontext("applicationContext-beans.xml"); UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager"); userManager.addUser("张三", "123"); // userManager.delUser(1); // userManager.modifyUser(1, "李四", "abc"); } }</wbr></wbr>
4.我们看看运行结果:
- 张三
- 123
- 你没有权限访问
- UserManagerImpl.addUser() -- name: 张三
张三 123 你没有权限访问 UserManagerImpl.addUser() -- name: 张三 <wbr> </wbr>
5. 如果目标类实现了接口,默认采用JDK动态代理来实现AOP
如果目标类没有实现接口,必须添加CGLIB支持,Spring会自动的在JDK和CGLIB代理之间切换
如果目标类实现了接口,可以定义让spring强制使用CGLIB代理
如何强制使用CGLIB代理实现AOP
将<aop:config>定义为<aop:config proxy-target-class="true">,
并且要引入CGLIB包:SPRING_HOME\lib\cglib\*.jar
JDK和CGLib的区别:
spring对AOP的支持
*如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
* 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
*如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
如何强制使用CGLIB实现AOP?
* 添加CGLIB库,SPRING_HOME/cglib/*.jar
* 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
JDK动态代理和CGLIB字节码生成的区别?
* JDK动态代理只能对实现了接口的类生成代理,而不能针对类
* CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
实例解析:
UserManager接口
[java] view plain copy print ?
- package com.macower.spring.proxy;
-
- public interface UserManager {
- public void addUser(String id, String password);
- public void delUser(String id);
- }
package com.macower.spring.proxy; public interface UserManager { public void addUser(String id, String password); public void delUser(String id); }
接下来是其实现类 UserManagerImpl
[java] view plain copy print ?
- package com.macower.spring.proxy;
-
- public class UserManagerImpl implements UserManager {
-
- public void addUser(String id, String password) {
- System.out.println(".: 掉用了UserManagerImpl.addUser()方法! ");
-
- }
-
- public void delUser(String id) {
- System.out.println(".: 掉用了UserManagerImpl.delUser()方法! ");
-
- }
- }
package com.macower.spring.proxy; public class UserManagerImpl implements UserManager { public void addUser(String id, String password) { System.out.println(".: 掉用了UserManagerImpl.addUser()方法! "); } public void delUser(String id) { System.out.println(".: 掉用了UserManagerImpl.delUser()方法! "); } }
JDK动态代理类
[java] view plain copy print ?
- package com.macower.spring.proxy;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
-
-
-
-
-
-
- public class JDKProxy implements InvocationHandler {
-
- private Object targetObject;
-
- public Object newProxy(Object targetObject) {
- this.targetObject = targetObject;
- return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
- targetObject.getClass().getInterfaces(), this);
- }
-
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- checkPopedom();
- Object ret = null;
- ret = method.invoke(targetObject, args);
- return ret;
- }
-
- private void checkPopedom() {
- System.out.println(".:检查权限 checkPopedom()!");
- }
- }
package com.macower.spring.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * * JDK动态代理类 * @author Macower * */ public class JDKProxy implements InvocationHandler { private Object targetObject;//需要代理的目标对象 public Object newProxy(Object targetObject) {//将目标对象传入进行代理 this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);//返回代理对象 } public Object invoke(Object proxy, Method method, Object[] args)//invoke方法 throws Throwable { checkPopedom();//一般我们进行逻辑处理的函数比如这个地方是模拟检查权限 Object ret = null; // 设置方法的返回值 ret = method.invoke(targetObject, args); //调用invoke方法,ret存储该方法的返回值 return ret; } private void checkPopedom() {//模拟检查权限的例子 System.out.println(".:检查权限 checkPopedom()!"); } }
CGLibProxy动态代理类
[java] view plain copy print ?
- package com.macower.spring.proxy;
-
- import java.lang.reflect.Method;
-
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
-
-
-
-
-
-
-
- public class CGLibProxy implements MethodInterceptor {
-
- private Object targetObject;
-
- public Object createProxyObject(Object obj) {
- this.targetObject = obj;
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(obj.getClass());
- enhancer.setCallback(this);
- Object proxyObj = enhancer.create();
- return proxyObj;
- }
-
- public Object intercept(Object proxy, Method method, Object[] args,
- MethodProxy methodProxy) throws Throwable {
- Object obj = null;
- if ("addUser".equals(method.getName())) {
- checkPopedom();
- }
- obj = method.invoke(targetObject, args);
- return obj;
- }
-
- private void checkPopedom() {
- System.out.println(".:检查权限 checkPopedom()!");
- }
- }
package com.macower.spring.proxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * CGLibProxy动态代理类的实例 * * @author Macower * */ public class CGLibProxy implements MethodInterceptor { private Object targetObject;// CGLib需要代理的目标对象 public Object createProxyObject(Object obj) { this.targetObject = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); enhancer.setCallback(this); Object proxyObj = enhancer.create(); return proxyObj;// 返回代理对象 } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object obj = null; if ("addUser".equals(method.getName())) {// 过滤方法 checkPopedom();// 检查权限 } obj = method.invoke(targetObject, args); return obj; } private void checkPopedom() { System.out.println(".:检查权限 checkPopedom()!"); } }
下面来测试下
[java] view plain copy print ?
- package com.macower.spring.proxy;
-
- public class Client {
-
- public static void main(String[] args) {
-
- UserManager userManager = (UserManager) new CGLibProxy()
- .createProxyObject(new UserManagerImpl());
- System.out.println("-----------CGLibProxy-------------");
- userManager.addUser("Macower", "root");
- System.out.println("-----------JDKProxy-------------");
- JDKProxy jdkPrpxy = new JDKProxy();
- UserManager userManagerJDK = (UserManager) jdkPrpxy
- .newProxy(new UserManagerImpl());
- userManagerJDK.addUser("Macower", "root");
- }
-
- }
package com.macower.spring.proxy; public class Client { public static void main(String[] args) { UserManager userManager = (UserManager) new CGLibProxy() .createProxyObject(new UserManagerImpl()); System.out.println("-----------CGLibProxy-------------"); userManager.addUser("Macower", "root"); System.out.println("-----------JDKProxy-------------"); JDKProxy jdkPrpxy = new JDKProxy(); UserManager userManagerJDK = (UserManager) jdkPrpxy .newProxy(new UserManagerImpl()); userManagerJDK.addUser("Macower", "root"); } }
执行结果是:
[java] view plain copy print ?
- -----------CGLibProxy-------------
- .:检查权限 checkPopedom()!
- .: 掉用了UserManagerImpl.addUser()方法!
- -----------JDKProxy-------------
- .:检查权限 checkPopedom()!
- .: 掉用了UserManagerImpl.addUser()方法!
-----------CGLibProxy------------- .:检查权限 checkPopedom()! .: 掉用了UserManagerImpl.addUser()方法! -----------JDKProxy------------- .:检查权限 checkPopedom()! .: 掉用了UserManagerImpl.addUser()方法!
JDK代理是不需要以来第三方的库,只要要JDK环境就可以进行代理,它有几个要求
* 实现InvocationHandler
* 使用Proxy.newProxyInstance产生代理对象
* 被代理的对象必须要实现接口
CGLib 必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承
但是针对接口编程的环境下推荐使用JDK的代理
在Hibernate中的拦截器其实现考虑到不需要其他接口的条件Hibernate中的相关代理采用的是CGLib来执行
所以在是实际的开发当中,开发人员应该根据实际的需求来选择合适的代理工具。
总结完毕!