注解
注解的定义
//定义属性 @interface myAnnotation{ int age(); String name(); }
注解的使用
//注解的作用目标 //一般用在类,方法,构造器,参数,局部变量,前 @MyAnno1 public class Demo1 { @MyAnno1 private String name; @MyAnno1 public Demo1() { } @MyAnno1 public void fun1() { } public void fun2(@MyAnno1 String name) { @MyAnno1 String username = "hello"; } }
//对于定义了属性的注解的使用 @MyAnnotation(age=32,name="sma") public class demo{ }
注解属性的类型
只能是
/* > 8种基本类型 > String > Enum > Class > 注解类型 > 以上类型的一维数组类型 */
注解的额外内容
1.默认值
@interface MyAnno2 { int age() default 100; String name(); }
使用时,该属性可以不赋值。
2.value属性。
注解有一个属性名称可以叫value,使用注解是,可以省略value=
3.作用范围限定
在定义注解前加上,比如
//限定注解MyAnno1只能在类,方法和成员变量前使用 @Target(value={ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @interface MyAnno1 { }
4保留策略
@Retention(RetentionPolicy.RUNTIME) @interface MyAnno1 { }
枚举RetentionPolicy有SOURCE,CLASS,RUNTIME,分别说明注解会保留在其中。
注意:要反射注解,只有使用RUNTIME。
反射注解
//反射泛型 abstract class A<T>{ public A(){ } } class B extentds A<String>{ } // 现在在其他某处使用类B,B b=new B(),想知道父类泛型具体是什么类。 在A的构造函数加入如下代码,具体执行在new B()时进行 Class clazz = this.getClass();//得到子类的类型 Type type = clazz.getGenericSuperclass();//获取传递给父类参数化类型 ParameterizedType pType = (ParameterizedType) type;//它就是A<String> Type[] types = pType.getActualTypeArguments();//它就是一个Class数组 Class c = (Class)types[0];//它就是String //可以连在一起写成 // Class c = (Class)((ParameterizedType)this.getClass() // .getGenericSuperclass()).getActualTypeArguments()[0]; // // System.out.println(c.getName());
反射注解
//对于类A和注解MyAnno1 @MyAnno1(name="A类", age=1, sex="男") class A { @MyAnno1(name="fun1方法", age=2, sex="女") public void fun1() { } } @Retention(RetentionPolicy.RUNTIME) @interface MyAnno1 { String name(); int age(); String sex(); }
分别获取类和方法上的注解
//获取类A上的注解 /* * 1. 得到作用目标 */ Class<A> c = A.class; /* * 2. 获取指定类型的注解 */ MyAnno1 myAnno1 = c.getAnnotation(MyAnno1.class); System.out.println(myAnno1.name() + ", " + myAnno1.age() + ", " + myAnno1.sex()); //获取方法上的注解 /* * 1. 得到作用目标 */ Class<A> c = A.class; Method method = c.getMethod("fun1"); /* * 2. 获取指定类型的注解 */ MyAnno1 myAnno1 = method.getAnnotation(MyAnno1.class); System.out.println(myAnno1.name() + ", " + myAnno1.age() + ", " + myAnno1.sex());
Bean工厂
先声明若干类和接口
//以下存在于多个文件 public class Teacher { private String tid; private String name; ....................... //getter and setter ..... } public class Student { private String number; private String name; private int age; private String sex; private Teacher teacher; public Teacher getTeacher() { return teacher; //getter and setter ..... } import cn.itcast.domain.Student; public interface StudentDao { void add(Student stu); void update(Student stu); } public class StudentImpl implements StudentDao { @Override public void add(Student stu) { System.out.println("StudentImpl.add()"); } @Override public void update(Student stu) { System.out.println("StudentImpl.update()"); } } public class StudentImpl2 implements StudentDao { @Override public void add(Student stu) { System.out.println("StudentImp2.add()"); } @Override public void update(Student stu) { System.out.println("StudentImp2.update()"); } } public interface StudentService { void login(); } public class StudentServiceImpl implements StudentService { private StudentDao studentDao = null; // 谁调用service方法,谁就需要先调用本方法,提供dao public void setStudentDao(StudentDao studentDao) { this.studentDao = studentDao; } public void login() { studentDao.add(null); studentDao.update(null); } }
然后在一个xml文件配置这些类的对象
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="stu1" className="cn.itcast.domain.Student"> <property name="number" value="ITCAST_1001"/> <property name="name" value="zhangSan"/> <property name="age" value="29"/> <property name="sex" value="male"/> <property name="teacher" ref="t1"/><!-- ref的值必须是另一个been的id --> </bean> <bean id="stu2" className="cn.itcast.domain.Student"> <property name="number" value="ITCAST_1002"/> <property name="name" value="wangWu"/> <property name="age" value="94"/> <property name="sex" value="female"/> <property name="teacher" ref="t1"/><!-- ref的值必须是另一个been的id --> </bean> <bean id="t1" className="cn.itcast.domain.Teacher"> <property name="tid" value="TEACHER_2001" /> <property name="name" value="liSi" /> <property name="salary" value="123.456" /> </bean> <bean id="stuDao" className="cn.itcast.dao.impl.StudentImpl2"> </bean> <bean id="stuService" className="cn.itcast.service.impl.StudentServiceImpl"> <property name="studentDao" ref="stuDao"/> </bean> </beans>
在需要的时候,从bean.xml中生成对象并使用
BeanFactory bf = new BeanFactory("beans.xml"); Student s1 = (Student)bf.getBean("stu1"); StudentDao stuDao = (StudentDao)bf.getBean("stuDao"); stuDao.add(null); stuDao.update(null); StudentService service = (StudentService) bf.getBean("stuService"); service.login();
动态代理
目的:现在有若干个接口,要得到一个对象,这个对象实现了这些接口的方法。
思考;
1.这个对象的类名并不重要,我们可以用Object来表示,如果有个Object o这个满足要求的对象,我们可以将其转化成接口类型,
然后调用接口方法。
2.接口中的方法由谁来实现?
这里使用InvocationHandler接口,实现其invoke方法
public Object invoke(Object proxy,Method m,Object[] args){
//具体实现
.....
}
这样我们调用我们接口中的方法其实就是调用了invoke里面的内容
其中Method就是接口中的Method,接口方法的参数会传入args中。
interface A { public void a(); public void aa(); public Object aaa(String s, int i); } interface B { public void b(); public void bb(); } @Test public void fun1() { /* * 三大参数 * 1. ClassLoader * 方法需要动态生成一个类,这个类实现了A、B接口,然后创建这个类的对象! * 需要生成一个类,这个类也需要加载到方法区中,谁来加载,当然是ClassLoader!!! * * 2. Class[] interfaces * 它是要实现的接口们 * * 3. InvocationHandler * 它是调用处理器 * 敷衍它! * * 代理对象的实现的所有接口中的方法,内容都是调用InvocationHandler的invoke()方法。 */ ClassLoader loader = this.getClass().getClassLoader(); InvocationHandler h = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("你好,动态代理!"); if(args[0]!=null){ System.out.println(args[0]); } return "返回的字符串"; } }; // 使用三大参数创建代理对象!!! Object o = Proxy.newProxyInstance(loader, new Class[]{A.class, B.class}, h); // 强转成A和B类型,成功了! A a = (A) o; Object result = a.aaa("hello", 100); System.out.println(result); }
控制台输出
你好,动态代理!
hello
返回的字符串
动态代理的应用1:增强
// 服务员 public interface Waiter { // 服务 public void serve(); } public class ManWaiter implements Waiter { public void serve() { System.out.println("服务中..."); } } public class Demo2 { @Test public void fun1() { Waiter manWaiter = new ManWaiter();//目标对象 /* * 给出三个参数,来创建方法,得到代理对象 */ ClassLoader loader = this.getClass().getClassLoader(); Class[] interfaces = {Waiter.class}; InvocationHandler h = new WaiterInvocationHandler(manWaiter);//参数manWaiter表示目标对象 // 得到代理对象,代理对象就是在目标对象的基础上进行了增强的对象! Waiter waiterProxy = (Waiter)Proxy.newProxyInstance(loader, interfaces, h); waiterProxy.serve();//前面添加“您好”, 后面添加“再见” } } class WaiterInvocationHandler implements InvocationHandler { private Waiter waiter;//目标对象 public WaiterInvocationHandler(Waiter waiter) { this.waiter = waiter; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("您好!"); this.waiter.serve();//调用目标对象的目标方法 System.out.println("再见!"); return null; } }
例子2:增强
public interface Waiter { // 服务 public void serve(); public void shouQian(); } public class ManWaiter implements Waiter { public void serve() { System.out.println("服务中..."); } public void shouQian() { System.out.println("收钱!"); } } public interface AfterAdvice { public void after(); } public interface BeforeAdvice { public void before(); } public class Demo3 { @Test public void fun1() { ProxyFactory factory = new ProxyFactory();//创建工厂 factory.setTargetObject(new ManWaiter());//设置目标对象 factory.setBeforeAdvice(new BeforeAdvice() {//设置前置增强 public void before() { System.out.println("您好不好!"); } }); factory.setAfterAdvice(new AfterAdvice() {//设置后置增强 public void after() { System.out.println("再见不见!"); } }); Waiter waiter = (Waiter)factory.createProxy(); waiter.shouQian(); } } public class ProxyFactory { private Object targetObject;//目标对象 private BeforeAdvice beforeAdvice;//前置增强 private AfterAdvice afterAdvice;//后置增强 /** * 用来生成代理对象 * @return */ public Object createProxy() { /* * 1. 给出三大参数 */ ClassLoader loader = this.getClass().getClassLoader(); Class[] interfaces = targetObject.getClass().getInterfaces(); InvocationHandler h = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* * 在调用代理对象的方法时会执行这里的内容 */ // 执行前置增强 if(beforeAdvice != null) { beforeAdvice.before(); } Object result = method.invoke(targetObject, args);//执行目标对象的目标方法 // 执行后置增强 if(afterAdvice != null) { afterAdvice.after(); } // 返回目标对象的返回值 return result; } }; /* * 2. 得到代理对象 */ Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h); return proxyObject; } public Object getTargetObject() { return targetObject; } public void setTargetObject(Object targetObject) { this.targetObject = targetObject; } public BeforeAdvice getBeforeAdvice() { return beforeAdvice; } public void setBeforeAdvice(BeforeAdvice beforeAdvice) { this.beforeAdvice = beforeAdvice; } public AfterAdvice getAfterAdvice() { return afterAdvice; } public void setAfterAdvice(AfterAdvice afterAdvice) { this.afterAdvice = afterAdvice; } }