上一章讲了通过动态代理实现了一个AOP,只是一个了解一下概念,那么我们实现一个简单的框架的AOP。那么我们来个复杂的代理;用到了工厂模式、文件读取、JavaBan、动态代理、内省等知识。如果这些还不明白的话去看一下我的前面写的教程。
需求:我们的用户管理时都要记录开始日志与结束日志
1.创建一个类
public class User{
private String name;
private String pwd;
public User() {
}
public User(String name, String pwd) {
this.name = name;
this.pwd = pwd;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
2.定义一个管理接口
public interface Imanger {
public void add(User U);
}
3.用一个类管理这个接口,将来也是被代理对象
public class UserManger implements Imanger {
private List<User> list=new ArrayList<>();
@Override
public void add(User U) {
System.out.println("-----正式操作--添加用户");
list.add(U);
System.out.println("添加成功:"+U.toString());
}
}
4.写个切面接口
public interface Advice {
public void Startadvice();
public void endadvice();
}
5.写一个切面实现类 代来是这个是切面层
package com;
//---------------AOP 这个是切面层
public class LogAdvice implements Advice{
@Override
public void Startadvice() {
System.out.println("---开始记录日志----");
}
@Override
public void endadvice() {
System.out.println("---业务操作结束------");
}
}
6.代理工厂利用Bean 实现代理方法
package com;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//---代理工厂利用Bean 实现代理方法
public class ProxyFactoryBean implements InvocationHandler {
private Object target;
private Advice advice;
//获取代理对象
public Object getProxy(){
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
return proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
advice.Startadvice();
Object res=null;
res=method.invoke(target,objects);
advice.endadvice();
return res;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
}
7.配置一个文件 用于读取组装信息
bean=com.ProxyFactoryBean
bean.target=com.UserManger
bean.advice=com.LogAdvice
8.创建组装工厂(这部分用到了内省,不懂的可以[点这里] 我这里没有用try语块而是通过throw方式,目的是为了让大家更容易阅读。(https://blog.csdn.net/weixin_44690195/article/details/106710618))
package com;
import aop.Advice;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class BeanFactory {
Properties prop=new Properties();//流容器
public BeanFactory(InputStream in){
try {
prop.load(in);//载入流
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getBean(String name) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IntrospectionException, InvocationTargetException {
String classname = prop.getProperty(name);//获取代理名称
Object bean = null;//代理中心
Class<?> aClass = Class.forName(classname);//装载类
bean = aClass.newInstance();//把类实例化
Object target = Class.forName(prop.getProperty(name + ".target")).newInstance();//装载被代理并实例化(注意一定要实例化)
Object advice = Class.forName(prop.getProperty(name + ".advice")).newInstance();//同上
BeanInfo beanInfo = Introspector.getBeanInfo(aClass);//把类反射
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();//获取全部成员
//遍历成员
for(PropertyDescriptor pb:propertyDescriptors){
String propertyname=pb.getName();//获取成员名称
Method writeMethod = pb.getWriteMethod();//打开Set开关
if ("target".equals(propertyname)){
writeMethod.invoke(bean,target);//把对像写入
} else if ("advice".equals(propertyname)){
writeMethod.invoke(bean,advice);//同上
}
}
return bean;
}
}
9.测试成果
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/bean.properties");
BeanFactory bf=new BeanFactory(in);
ProxyFactoryBean proxyFactorybean = (ProxyFactoryBean)bf.getBean("bean");
Imanger proxy =(Imanger) proxyFactorybean.getProxy();
proxy.add(new User ("Admin","password"));
效果
---开始记录日志----
-----正式操作--添加用户
添加成功:User{
name='Admin', pwd='password'}
---业务操作结束------
总结
这里对于新手来说有很多难理解的东西,可能会因一句代码就会让程序跑不出来。所以一定要自己写一次。