Maven项目&Spring AOP基础(一)
Spring AOP的底层机制就是动态代理。而代理模式又分为:静态代理、动态代理。
静态代理的角色分为:
抽象角色 : 一般使用接口或者抽象类来实现,例如:租房这个动作
真实角色 : 被代理的角色,例如:房东
代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 ,例如:中介
客户 : 使用代理角色来进行一些操作 ,例如:要租房的房客
代码实现1
抽象角色:Rent.class
public interface Rent {
void rentHouse();
}
真实角色:Host .class
public class Host implements Rent {
public void rentHouse() {
System.out.println("我的房子要出租。");
}
}
代理角色:Proxy.class
public class Proxy implements Rent {
Host host ;
public Proxy(Host host) {
this.host = host;
}
//租房
public void rentHouse() {
host.rentHouse();
}
//看房
public void seeHouse(){
System.out.println("带房客看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
客户 :Client.class
public class Client {
public static void main(String[] args) {
//房东要租房
Host host = new Host();
//中介帮助房东
Proxy proxy = new Proxy(host);
//房客找中介!
proxy.rentHouse();
//中介带房客看房
proxy.seeHouse();
//中介收中介费
proxy.fare();
}
}
代码实现2
抽象角色:业务接口UserService
public interface UserService {
void add();
void update();
void query();
void delete();
}
真实角色:实现接口完成这些增删改查操作UserServiceImpl
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("新增用户");
}
public void update() {
System.out.println("修改用户");
}
public void query() {
System.out.println("查询用户");
}
public void delete() {
System.out.println("删除用户");
}
}
现需要给上述每个实现方法中都增加打印日志的功能。
如果直接在每个方法中增加打印日志的代码,就改变了原有的业务逻辑,那么在不改变原有业务的情况下,就需要使用到代理角色来实现。
代理角色:设置一个代理类来处理日志UserServiceProxyImpl
public class UserServiceProxyImpl implements UserService {
UserServiceImpl userServiceImpl ;
public UserServiceProxyImpl(UserServiceImpl userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
public void add() {
log("add");
userServiceImpl.add();
}
public void update() {
log("update");
userServiceImpl.update();
}
public void query() {
log("query");
userServiceImpl.query();
}
public void delete() {
log("delete");
userServiceImpl.delete();
}
public void log(String msg){
System.out.println(msg+"了一个用户");
}
}
客户:测试访问类 UserServiceTest
public class UserServiceTest {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
UserServiceProxyImpl userServiceProxy = new UserServiceProxyImpl(userService);
userServiceProxy.add();
}
}
从上述代码可以看出,AOP中最核心的思想就是不改变原来的代码的情况下,实现了对原有功能的增强。
动态代理
动态代理的角色和静态代理的一样 .
动态代理的代理类是动态生成的 . 静态代理的代理类是提前写好的
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理。
以下通过JDK的原生代码来实现,JDK的动态代理需要了解两个类
核心 : InvocationHandler 和Proxy
改造上述两个示例。
代码实现1
抽象角色:Rent
public interface Rent {
void rentHouse();
}
真实角色:RealHost
public class RealHost implements Rent
{
@Override
public void rent()
{
System.out.println("I want to rent my house");
}
}
代理角色:DynamicProxy
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy implements InvocationHandler
{
// 这个就是要代理的真实对象(例如:租房)
private Object realObj;
// 构造方法,给要代理的真实对象赋初值
public DynamicProxy(Object obj)
{
this.realObj = obj;
}
//生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
/*
* 通过Proxy的newProxyInstance方法来创建的代理对象,其三个参数
* 第一个参数 handler.getClass().getClassLoader() , 这里使用handler这个类的ClassLoader对象来加载我们的代理对象
* 第二个参数 renObject.getClass().getInterfaces(), 这里为代理对象提供的接口是真实对象所调用的接口,表示要代理的是该真实对象,这样就能调用这组接口中的方法了
* 第三个参数 handler, 这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
realObj.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object object, Method method, Object[] args)
throws Throwable
{
//在代理真实对象前可以添加一些自己的操作
System.out.println("before rent house");
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(realObj, args);
//在代理真实对象后也可以添加一些自己的操作
System.out.println("after rent house");
return null;
}
客户:Client
public class Client {
public static void main(String[] args)
{
//要代理的真实对象
Rent realHost = new RealHost();
//要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
DynamicProxy handler = new DynamicProxy(realHost);
Rent proxy = (Rent) handler.getProxy();
proxy.rent();
}
}
输出结果:
before rent house
I want to rent my house
after rent house
代码实现2
抽象角色:业务接口UserService
public interface UserService {
void add();
void update();
void query();
void delete();
}
真实角色:实现增删改查操作UserServiceImpl
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("新增用户");
}
public void update() {
System.out.println("修改用户");
}
public void query() {
System.out.println("查询用户");
}
public void delete() {
System.out.println("删除用户");
}
}
代理角色:DynamicProxyHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxyHandler implements InvocationHandler {
private Object object;
public DynamicProxyHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(object,args);
log(method.getName());
return null;
}
public Object getProxyObj(){
ClassLoader classLoader = DynamicProxyHandler.class.getClassLoader();
Class<?>[] interfaces = object.getClass().getInterfaces();
return Proxy.newProxyInstance(classLoader,interfaces,this);
}
public void log(String msg){
System.out.println(msg+"了一个用户。");
}
}
客户:测试访问类 UserServiceTest
public class UserServiceTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
DynamicProxyHandler userServiceProxy = new DynamicProxyHandler(userService);
UserService proxyObj = (UserService) userServiceProxy.getProxyObj();
proxyObj.add();
proxyObj.delete();
proxyObj.update();
proxyObj.query();
}
}
输出结果:
新增用户
add了一个用户。
删除用户
delete了一个用户。
修改用户
update了一个用户。
查询用户
query了一个用户。