<aops>
<aop>
<method>washHand</method>
<type>before</type>
<method>eat</method>
</aop>
<aop>
<method>bath</method>
<type>after</type>
<method>eat</method>
</aop>
</aops>
package com.example.aopdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 通过启动TestAop
* 更改classpath下的aops.xml
* 自动进行方法的更新 前置方法的更改
*
* 面向对象:将需求功能划分为不同的,独立,封装良好的类,并让它们
* 通过继承和多态实现相同和不同的行为.
*
* 面向切面:将通用需求功能从众多类中分离出来,使得很多类共享一个
* 行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可.
*
* 面向切面编程:
* - 分离代码的耦合(高内聚,低耦合)
* - 业务逻辑变化不需要修改源代码/不用重启
* - 加快编程和测试速度
*
* - 一个概念/规范,没有限定语言
* - 不是取代OOP编程,而是OOP的补充,和数据库的触发器有点相似
* 主要内容
* - Aspect:配置文件,包括一些Pointcut和相应的Advice
* - Joint point:在程序中明确定义的点,如方法调用,对类成员访问等
* - Pointcut:一组joint point,可以通过逻辑关系/通配符/正则等组合起来,
* 定义了相应advice将要发生的地方
* - Advice:定义了在pointcut处要发生的动作,通过before/after/around/来关联
* - weaving:advice代码在具体joint point的关联方式
*/
@SpringBootApplication
public class AopDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AopDemoApplication.class, args);
}
}
package com.example.aopdemo;
public interface Person {
void eat();
void washHand();
void bath();
}
package com.example.aopdemo.impl;
import com.example.aopdemo.Person;
public class PersonImpl implements Person {
@Override
public void eat() {
System.out.println("想吃牛油果");
}
@Override
public void washHand() {
System.out.println("洗手讲卫生");
}
@Override
public void bath() {
System.out.println("洗澡去臭臭");
}
}
package com.example.aopdemo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
static String beforeMethod = "";
static String afterMethod = "";
private Person receiverObject;
public ProxyHandler(Person person){
this.receiverObject=person;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//处理before方法
if(beforeMethod!=null && beforeMethod.length()>0){
ClassLoader c1 = ProxyHandler.class.getClassLoader();
Class<?> c = c1.loadClass(receiverObject.getClass().getName());
Method m = c.getMethod(beforeMethod);
Object obj = c.newInstance();
m.invoke(obj);
}
//处理目标方法
Object result = method.invoke(receiverObject, args);
//处理after方法
if(afterMethod!=null && afterMethod.length()>0){
method.invoke(receiverObject,args);
ClassLoader c1 = ProxyHandler.class.getClassLoader();
Class<?> c = c1.loadClass(receiverObject.getClass().getName());
Method m = c.getMethod(afterMethod);
Object obj = c.newInstance();
m.invoke(obj);
}
return result;
}
}
package com.example.aopdemo;
import java.nio.file.*;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ResourceListener {
private static ExecutorService fixedThreadPool= Executors.newCachedThreadPool();
private WatchService ws;
private String listenerPath;
private ResourceListener(String path){
try
{
ws=FileSystems.getDefault().newWatchService();
this.listenerPath=path;
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void start(){
fixedThreadPool.execute(new Listener(ws, listenerPath));
}
public static void addListener(String path){
try{
ResourceListener resourceListener=new ResourceListener(path);
Path p=Paths.get(path);
p.register(resourceListener.ws, StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_CREATE);
resourceListener.start();
}
catch (Exception e){
e.printStackTrace();
}
}
class Listener implements Runnable{
WatchService ws;
String listenerPath;
Listener(WatchService ws,String listenerPath){
this.ws = ws;
this.listenerPath = listenerPath;
}
@Override
public void run() {
try {
while(true){
WatchKey watchKey = ws.take();
List<WatchEvent<?>> watchEvents = watchKey.pollEvents();
for(WatchEvent<?> event : watchEvents){
String context = event.context().toString();//对象
String kind = event.kind().toString();//变更类型
if(context.equals("aops.xml")){
if(kind.equals("ENTRY_MODIFY")){
XmlReader.readXml(listenerPath+"/"+event.context());
}
}
}
watchKey.reset();
}
} catch (InterruptedException e) {
e.printStackTrace();
try {
ws.close();
} catch (Exception e1) {
}
}
}
}
}
package com.example.aopdemo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class XmlReader {
public static void readXml(String filePath){
String xml = load(filePath);
try{
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
Document document;
DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
StringReader sr = new StringReader(xml);
InputSource is = new InputSource(sr);
document = dbBuilder.parse(is);
Element root = document.getDocumentElement();
findMethod(root.getChildNodes());
}
catch(Exception e){
e.printStackTrace();
}
}
public static void findMethod(NodeList elementList){
for (int i = 0; i < elementList.getLength(); i++) {
Node elementNode = elementList.item(i);
//System.out.println("allnode: "+elementNode.getNodeName());
if (elementNode.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) elementNode;
String name = element.getNodeName();
if(name.equalsIgnoreCase("aop")){
readMethod(element.getChildNodes());
}
else{
findMethod(element.getChildNodes());
}
}
}
}
private static void readMethod(NodeList elementList){
String methodName = "";
for (int i = 0; i < elementList.getLength(); i++) {
Node elementNode = elementList.item(i);
if (elementNode.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) elementNode;
String name = element.getNodeName();
if(name.equals("method")){
if(methodName==null||methodName.length()==0) {
methodName = element.getFirstChild().getTextContent();
}
}
else if(name.equals("type")){
String type = element.getFirstChild().getTextContent();
if(type.equals("after")){
ProxyHandler.afterMethod = methodName;
}
else{
ProxyHandler.beforeMethod = methodName;
}
}
}
}
}
private static String load(String path){
try{
File file = new File(path);
FileReader reader = new FileReader(file);
BufferedReader bReader = new BufferedReader(reader);
StringBuilder sb = new StringBuilder();
String s = "";
while ((s =bReader.readLine()) != null) {
sb.append(s + "\n");
//System.out.println(s);
}
bReader.close();
return sb.toString();
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
}
package com.example.aopdemo;
import com.example.aopdemo.XmlReader;
import com.example.aopdemo.impl.PersonImpl;
import com.sun.prism.ResourceFactoryListener;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
public class TestAop {
public static void initXml() {
XmlReader.readXml("C:\\Users\\Administrator\\IdeaProjects\\geektime-spring-family-learning\\aop-demo\\src\\main\\resources\\aops.xml");
ResourceListener.addListener("C:\\Users\\Administrator\\IdeaProjects\\geektime-spring-family-learning\\aop-demo\\src\\main\\resources");
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
TestAop.initXml();
Person action = new PersonImpl();
ProxyHandler mh = new ProxyHandler(action);
ClassLoader c1 = TestAop.class.getClassLoader();
Class<?> proxyClass = Proxy.getProxyClass(c1, new Class<?>[]{Person.class});
Person proxy = (Person) proxyClass.getConstructor(new Class[]{InvocationHandler.class}).newInstance(new Object[]{mh});
while(true){
proxy.eat();
try{
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}