javaEE-Annotation(注解)
来源:互联网 发布:代申请淘宝大v 编辑:程序博客网 时间:2024/05/20 13:37
所有注解都是类
2:所有注解类都默认是Annotation接口的子类。
3:定义方式:
public@interface SomeAnotation{
}
4:可以注解的位置
类上
方法上
成员变量上。
返回值上
参数上
局部变量
import org.junit.Test;@MyTestpublic class RunTest {@MyTestprivate int age;@MyTest()public void tt(@MyTest()int a){@MyTestint xx=0;}}
5:如果定义了一个注解之后,没有说明这个注解可以注解的位置,则这个注解就可以注解在所有位置上。
可以通过另一个注解,限制自定义的注解可以注解的位置:
通过@Target定义某个注解可以注解的位置.
以下定义某个注解只可以注解到方法上:
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
//设定注解可以注解的位置
@Target(value={ElementType.METHOD})
public @interface MyTest {
}
用途
1:在编译时起到限制的作用.
public class MyServlet extends HttpServlet {
@Override
publicvoid doGet(ServletRequestreq,String name)
throws ServletException,IOException {
}
因为父类中没有这个方法所以添加了@Overried以后,就会编译出错。
2:在运行时组反射使用
junit的机制就是通过注解反射boolean
isAnnotationPresent
(Class<? extendsAnnotation> annotationClass)
如果指定类型的注解存在于此元素上,则返回 true,否则返回 false。
注解存在的范围:
一个类:Retention,用于定义注解存在的策略:
java.lang.annotation
枚举 RetentionPolicy
三个常量:
枚举常量摘要
CLASS
编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。 在.class存在,在运行时擦除
RUNTIME
编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。运行时存在。
SOURCE
编译器要丢弃的注释。只在.java文件中存在@Overied
以下是经常使用的标准定义:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)[W1]
@Target(value={ElementType.METHOD})[W2]
public @interface MyTest {
}
以下是myUnit的测试类:
核心方法:
public class MyUnit {
public static void main(String[] args)throws Exception {
System.err.println("请输入准备被测试的类:");
Scanner sc = new Scanner(System.in);
String clsName = sc.nextLine();//clsName = "cn.itcast.demo.RunTest";
//根据类名获取这个类的字节
Class cls = Class.forName(clsName);
//实例化这个类,调用默认构造方法
Object obj = cls.newInstance();
//获取这个类中的所有方法
Method[] ms = cls.getDeclaredMethods();//只获取用户定义的方法,private && public
//cls.getMethods();获取这个类所方法,包括从父类中继承的方法
//遍历判断某个方法上是否存在注解
for(Method m:ms){
boolean boo2 =m.isAnnotationPresent(MyTest.class);//false[W3]
if(boo2){
if(m.getModifiers()==Modifier.PRIVATE){
System.err.println("这个私有的方法:"+m.getName()+",不支持运行...");
continue;
}
//运行这个方法
m.invoke(obj);
}
}
注解的实例化
永远都不要实例化注解类,因注解是由系统通过反射实例化的给注解定义属性/方法
如果某个注解需要一个标识,就给它定义一个属性.
定义的方法:
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.METHOD})
public @interface MyTest {
/**
* 对于一人注解类来说。
* value属性是官方建议取的名称
* 且value也是默认属性
* 以下定义的属性,因为没有默认值,所以用户
* 在使用时必须给显式的给值
*/
public String value();
/**
* 定义一个拥有默认值的属性
*/
public String name()default "NoName";
}
获取注解上的属性的值:
<A extends Annotation>
A
getAnnotation
(Class<A> annotationClass)
如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
public class AnlyValueDemo {
public static void main(String[] args)throws Exception {
RunTest run = new RunTest();
Method m1 = run.getClass().getMethod("bbb");
//获取这个方法上的注解的实例
MyTest mt = m1.getAnnotation(MyTest.class);[W1]
//获取这个注解上的属性的值
String name = mt.name();
String value = mt.value();
System.err.println(name+","+value);
}
}
用途:生成表结构并保存,以下是SUN公司提供的注解:
在系统中存在很多的注解,其中有些注解是给JDBC。
@Table – 定义一个类,这个类对应一个表-领域模型
@Column – 定义一个类其中的某个字段
@Id - 定义主键
@OnToMany
@OneToOne
@ManyToMany
通过注解直接保存对象
//对应的表叫users@Table(name="users")public class User {@Columnprivate String id;@Columnprivate String name;@Columnprivate String pwd;@Columnprivate Integer age;@Column(name="address")private String addr;public String getId() {return id;}public void setId(String id) {this.id = id;}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;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getAddr() {return addr;}public void setAddr(String addr) {this.addr = addr;}@Overridepublic String toString() {return "User [id=" + id + ", name=" + name + ", pwd=" + pwd + "]";}}
@Testpublic void save() throws Exception{//从前面页面接收User//User u = new User();//u.setId("U009");//u.setName("JackRose");//u.setPwd("3333");//u.setAge(89);//u.setAddr("中国");Contact c = new Contact();c.setId("AAAA");c.setName("DFSAFDS");c.setSex("1");QueryRunner run = new QueryRunner(DataSourceUtils.getDatasSource());run.save(c);}
//添加save方法/** * 对传递的bean进行分析 * 将t对象转成insert into users */public <T> T save(T t) throws Exception{//获取类Class<?> cls = t.getClass();//从这个字节码上获取name值这个就是表名Table table = cls.getAnnotation(Table.class);//获取表名String tableName = table.name();//组成insert into users(id,name,pwd) values('id',"name','');String sql = "insert into "+tableName;String cols="(";String values="values(";//获取所有声明的字段Field[] fs = cls.getDeclaredFields();//遍历所有字段for(Field f:fs){if(f.isAnnotationPresent(Column.class)){//获取列名String colName = f.getName();//获取column的对象Column col = f.getAnnotation(Column.class);if(col.name()!=null && !col.name().trim().equals("")){colName=col.name();}//获取列值f.setAccessible(true);//获取列值Object value = f.get(t);if(cols.equals("(")){cols+=colName;if(value instanceof String){values+="'"+value+"'";}else{values+=value;}}else{cols+=","+colName;if(value instanceof String){values+=",'"+value+"'";}else{values+=","+value;}}}}cols+=")";values+=")";sql = sql+cols+" "+values;System.err.println(sql);update(sql);return t;}
注解给反射用并控制事务
要求:
被代理类必须要拥有接口。
代理的两个核心类:
Proxy :在内存中生成接口的子类。
InvocationHandler : 执行句柄 ,在执行代理类的方法时,此Invocationhandler会拦截所有代理类的方法。
示例:要求对List进行代理:import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.List;public class ProxyDemo {public static void main(String[] args) throws Exception {//声明被代理类final List list = new ArrayList();//生成代理类Object obj = Proxy.newProxyInstance(ProxyDemo.class.getClassLoader(),new Class[]{List.class},new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.err.println("执行某个方法了:"+method.getName());//执行被代理类Object returnValue = method.invoke(list, args);return returnValue;}});//将代理类转换成接口的对象List list2 = (List) obj;list2.add("ddd");System.err.println(list2.get(0));}}
要求实现一个类可以对所有拥有接口的类都可以代理:
package cn.itcast.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 此类不但是工具类,且还是执行句柄 * */public class MyProxy2 implements InvocationHandler {/** * 声明被代理类 */private Object src;/** * 构造 中接收这个被代理的对象 */private MyProxy2(Object src){this.src=src;}/** * 提供一个静态方法返回代理对象 */public static Object factory(Object src){Object proxyedObj = Proxy.newProxyInstance(MyProxy2.class.getClassLoader(),src.getClass().getInterfaces(),new MyProxy2(src));return proxyedObj;}/** * 实现执行拦截方法 */public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.err.println("执行的方法是>>>>:+"+method.getName());Object rVlaue = method.invoke(src,args);return rVlaue;}}
代理所有Service,在代理类中开始事务
1:书写工具类,使用ThreadLocal模式管理当前线程对象
public class DataSourceUtils {private static DataSource ds;//声明ThreadLocal容器对象private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();static {ds = // 默认的读取c3p0-config.xml中默认配置new ComboPooledDataSource();}public static DataSource getDatasSource() {return ds;}//提供一个返回Connection的方法public static Connection getConn(){Connection con = null;//先从tl中获取数据con = tl.get();if(con==null){try{con = getDatasSource().getConnection();//放到tltl.set(con);}catch(Exception e){e.printStackTrace();}}return con;}}
2:声明两个dao
3: 声明Service必须要拥有接口
public class TxService implements ITxService {//注入两个daoprivate Dao1 dao1 = new Dao1();private Dao2 dao2 = new Dao2();public void save(){dao1.save();dao2.save();}}
4:完成事务的代理类
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.sql.Connection;/** * 事务的代理类,可以代理任意的Service */public class TxProxy implements InvocationHandler{private Object src;//声明被代理类对象private TxProxy(Object src){//在私有的构造中给成员设置值this.src=src;}/** * 提供一个静态的方法返回代理对象 */public static Object factory(Object src){Object proxyedObj = //生成被代理类的接口的子类Proxy.newProxyInstance(TxProxy.class.getClassLoader(),src.getClass().getInterfaces(), new TxProxy(src));return proxyedObj;}/** * 以下是执行的句柄,当调用代理类的任意方法时都会调用这个方法 * 在这儿是管理事务的关键 */public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//第一步:声明连接Connection con = null;Object returnValue = null;try{//第二步:获取连接con = DataSourceUtils.getConn();//第三步:设置事务的开始con.setAutoCommit(false);//第四步:调用目标类(被代理类)的方法returnValue = method.invoke(src, args);//第五步:调用如果成功con.commit();}catch(Exception e){con.rollback();throw e;}finally{con.close();DataSourceUtils.remove();}return returnValue;}}
5:声明Servlet并在servlet中通过代理获取到Service对象的实例
public class TxServlet extends HttpServlet {/** * 注入service的实例,必须要使用接口 */private ITxService service = (ITxService) TxProxy.factory(new TxService());public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {service.save();}}
6、修改Txproxy对某些方法开事务,某些方法不开事务
在需要事务的方法上添加事务注解。如果不需要事务,则不添加注解。import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target(value=ElementType.METHOD)public @interface Tx {}给需要的方法添加注解:public interface ITxService {@Txvoid save();public void query();}以下是代理的完整代码:(如果你就操作一条sql语句,没有必要开事务,如果是查询也没有必要开事务。以下就开事务: 对一表操作2(insert|update|delete)次以上. 或是操作多个表时。)package cn.itcast.utils;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.sql.Connection;import javax.ejb.TransactionAttribute;import javax.persistence.Transient;/** * 事务的代理类,可以代理任意的Service */public class TxProxy implements InvocationHandler{private Object src;//声明被代理类对象private TxProxy(Object src){//在私有的构造中给成员设置值this.src=src;}/** * 提供一个静态的方法返回代理对象 */public static Object factory(Object src){System.err.println("0:返回代理类");Object proxyedObj = //生成被代理类的接口的子类Proxy.newProxyInstance(TxProxy.class.getClassLoader(),src.getClass().getInterfaces(), new TxProxy(src));return proxyedObj;}/** * 以下是执行的句柄,当调用代理类的任意方法时都会调用这个方法 * 在这儿是管理事务的关键 */public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//判断是否有事务的注解if(!method.isAnnotationPresent(Tx.class)){System.err.println("没有事务的注解,用户不需要事务。直接执行目标方法");return method.invoke(src, args);}//第一步:声明连接Connection con = null;Object returnValue = null;try{//第二步:获取连接con = DataSourceUtils.getConn();//第三步:设置事务的开始System.err.println("设置事务的开始");con.setAutoCommit(false);//第四步:调用目标类(被代理类)的方法returnValue = method.invoke(src, args);//第五步:调用如果成功提交System.err.println("调用如果成功提交");con.commit();}catch(Exception e){System.err.println("调用不成功回滚");con.rollback();throw e;}finally{con.close();DataSourceUtils.remove();}return returnValue;}}
- javaEE-Annotation(注解)
- 注解(Annotation)--注解处理器
- 注解(Annotation)自定义注解
- 注解(Annotation)--注解处理器
- 注解(Annotation)--注解处理器
- JAVA 注解(annotation)
- 注解(Annotation)
- Annotation(注解)是什么?
- java 注解(Annotation)
- 注解(Annotation)
- 30、注解(Annotation)
- java 注解(annotation)
- JAVA 注解(Annotation)
- Java 注解(annotation)
- 注解(Annotation)
- Annotation(@注解)
- Annotation注解 (一)
- 自定义Annotation(注解)
- “网如人生”揭秘网站权重计算方法
- Quartus 建立SOPC项目下载到DE2中回送Hello
- Log Annonation例子
- Android中通过xml资源文件定义数组
- “网络”与“营销”的意义
- javaEE-Annotation(注解)
- Android实战技巧之六:PreferenceActivity使用详解
- js数组
- 苏宁张近东上两会,三提案招招逼阿里
- “网络写手”的互联网价值
- hibernate 提高数据库性能
- “艳门照”事件催生了在线照片合成发展
- Bash脚本之if-then语句
- SSH web开发架构(转载)