反射
(1) 在运行中分析类的能力
(2) 在运行中查看和操作对象
-基于反射自由创建对象
-反射构建出现在无法直接访问的类
-set或者get到无法访问的成员变量
-调用不可访问的方法
-实现通用的数组操作代码
-类似于函数指针的功能
(3) 代码示例
Object obj6 = Class.forName(“全限定类名”).newInstance();
Method m = Class.forName((“全限定类名”).getMethod(“当前类中的方法”);
m.invoke(params); //执行次方法
//获取当前类中的所有方法
Method[] methods = clazz.getDeclaredMethods();
(4) class.getField 获取当前类中的所有成员变量包括继承来的
class.getDeclareFiled 获取当前类中所有成员变量(不包括继承来的)
class.getMethod()同class.getField一样
class.getDeclareMethod同class.getDeclareFiled一样
(5) (6) 临时使一个类中private修饰的变量或者方法变为public的方式
m.setAccessible(true);
f.setAccessible(true);
java代理
(1)java代理分为静态代理和动态代理
(2)静态代理
代理对象持有目标对象的句柄
所有调用目标对象的方法,都调用代理对象的一个方法
对每一个方法都需要静态编码
(3) 静态代理实现较为简单,但是需要在代理对象中对每一个目标对象的方法进行重写,所以如果方法多了之后,代码量就会变的很大.
(4) 代码示例
//目标对象接口
public interface Subject{
public void request();
}
//目标对象
class SubjectImpl implements Subject{
public void request(){
System.out.println("I am dealing the request.");
}
}
//代理对象
class StaticProxy implements Subject{
//实际目标对象
private Subject subject;
public StaticProxy(Subject subject){
this.subject = subject;
}
public void request(){
System.out.println("PreProcess");
subject.request();
System.out.println("PostProcess");
}
}
//静态代理模式
public class StaticProxyDemo {
public static void main(String args[]){
//创建实际对象
SubjectImpl subject = new SubjectImpl();
//把实际对象封装到代理对象中
StaticProxy p = new StaticProxy(subject);
p.request();
}
}
动态代理
1 动态代理
-对目标对象的方法每次被调用,进行动态拦截 2 动态代理中最重要的是代理处理器
1 持有目标对象的句柄
2 实现invacationHandler接口
-实现invoke方法
-所有的代理对象方法调用,都会转发到invoke方法中来
-invoke的形参method,是指代理对象方法的调用
-在invoke内部,可以根据method指定代理对象方法的调用。
3 代理对象
-根据给定的接口,由Proxy类自动生成对象
-类型com.sun.proxy继承自java.lang.reflect.Proxy
-通常和目标对象实现同样的接口
-实现多个接口,接口的排序非常重要
4 代码示例
//目标对象接口
public interface Subject{
public void request();
}
//目标对象
class SubjectImpl implements Subject{
public void request(){
System.out.println("I am dealing the request.");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 代理类的调用处理器
*/
class ProxyHandler implements InvocationHandler{
private Subject subject;
public ProxyHandler(Subject subject){
this.subject = subject;
}
//此函数在代理对象调用任何一个方法时都会被调用。
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println(proxy.getClass().getName());
//定义预处理的工作,当然你也可以根据 method 的不同进行不同的预处理工作
System.out.println("====before====");
Object result = method.invoke(subject, args);
System.out.println("====after====");
return result;
}
}
import java.lang.reflect.Proxy;
//动态代理模式
public class DynamicProxyDemo {
public static void main(String[] args) {
//1.创建目标对象
SubjectImpl realSubject = new SubjectImpl();
//2.创建调用处理器对象
ProxyHandler handler = new ProxyHandler(realSubject);
//3.动态生成代理对象
Subject proxySubject =
(Subject)Proxy.newProxyInstance
(SubjectImpl.class.getClassLoader(),
SubjectImpl.class.getInterfaces(), handler);
//proxySubject真实类型com.sun.proxy.$Proxy0
//proxySubject继承Proxy类,实现Subject接口
//newProxyInstance的第二个参数,就是指定代理对象的接口
//4.客户端通过代理对象调用方法
//本次调用将自动被代理处理器的invoke方法接收
proxySubject.request();
System.out.println(proxySubject.getClass().getName());
System.out.println(proxySubject.getClass().getSuperclass().getName());
}
}
简略代理模式
package ceshi;
import java.util.Map;
/*
* 代理接口
* */
public interface IServiceProxy<T,K> {
void doServer(T s,K v);
}
package ceshi;
import java.util.Map;
/**
* @Description 代理实现类1
* @Auther hanlin
* @Date 2019/12/22 13:53
* @Version 1.0
**/
public class DoserverTest1 implements IServiceProxy {
@Override
public void doServer(Object s, Object v) {
System.out.println("这是测试1"+s+v);
}
}
package ceshi;
/**
* @Description 代理实现类2
* @Auther hanlin
* @Date 2019/12/22 13:58
* @Version 1.0
**/
public class DoserverTest2 implements IServiceProxy {
@Override
public void doServer(Object s, Object v) {
System.out.println("这是测试2"+s+v);
}
}
package ceshi;
/**
* @Description 代理对象类,用来操作公共部分,如公共报文头的操作,事务回滚,冲正,记录日志信息等
* @Auther hanlin
* @Date 2019/12/22 13:59
* @Version 1.0
**/
public class Proxy {
private IServiceProxy target = null;
public Proxy(IServiceProxy target){
this.target = target;
}
//执行真正业务逻辑处理的方法
public void invok(){
target.doServer(null,null);
}
}
结论:总而言之无论你先干什么总回先进入这个代理,执行完这个代理类的逻辑,然后在去执行你真正的业务逻辑,所以你写的每一个业务类都要实现我的doserver方法,然后在这个doserver方法中进行你全部的业务逻辑处理.
AOP编程
1 面向切面编程和面向对象编程的区别
面向对象:将需求功能划分为不同的独立的封装良好的类,并让他们通过继承和多态实现相同或者不同的行为
面向切面:将通用功能需求从更多类中分离出来,使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为就可以了.
2 Aop的主要内容
Aspect:配置文件,包括一些pointcut和相应的advice
Joint point: 在程序中明确定义的点,如方法调用和类成员的访问
Pointcut :一组joint point,可以通过逻辑关系/通配符/正则等组合起来/定义了相对的advice要发生的地方。
Advice:定义了在pointcut处要发生的动作,通过before/after/around/来关联
weaving:advice代码在joint pomt 的关联方式
3 代码示例
<--在aop配置文件中配置执行某个方法之前要干什么aop.xml-->
<aops>
<aop>
<method>washHand</method>
<type>before</type>
<method>eat</method>
</aop>
</aops>
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;
//读取xml配置文件
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;
}
}
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
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) {
}
}
}
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
//代理类
public class ProxyHandler implements InvocationHandler {
static String beforeMethod = "";
static String afterMethod = "";
private Person receiverObject;
public ProxyHandler(Person object){
this.receiverObject = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//处理before方法
if(beforeMethod!=null&&beforeMethod.length()>0){
ClassLoader cl = ProxyHandler.class.getClassLoader();
Class<?> c = cl.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 cl = ProxyHandler.class.getClassLoader();
Class<?> c = cl.loadClass(receiverObject.getClass().getName());
Method m=c.getMethod(afterMethod);
Object obj = c.newInstance();
m.invoke(obj);
}
return result;
}
}
//接口
public interface Person {
void eat();
void washHand();
void bath();
}
//接口实现类
public class PersonImpl implements Person {
public void eat() {
System.out.println("I am eating");
}
public void washHand() {
System.out.println("I am washing hands");
}
public void bath() {
System.out.println("I am bathing");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
//测试类
public class Main {
public static void initXml(){
XmlReader.readXml("aops.xml");
ResourceListener.addListener("E:/java/source/PMOOC04-03/");
}
public static void main(String[] args) throws Exception{
Main.initXml();
Person action = new PersonImpl();
ProxyHandler mh = new ProxyHandler(action);
ClassLoader cl = Main.class.getClassLoader();
Class<?> proxyClass = Proxy.getProxyClass(cl, 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(Exception e){
e.printStackTrace();
}
}
}
}