注解与XML配置的区别
注解:是一种分散式的元数据,与源代码耦合。 xml :是一种集中式的元数据,与源代码解耦。
因此注解和XML的选择上可以从两个角度来看:分散还是集中,源代码耦合/解耦。
注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作。如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO 的属性名、类型等信息,如果关系表字段和 PO 属性名、类型都一致,您甚至无需编写任务属性映射信息——因为这些信息都可以通过 Java 反射机制获取。 注释和 Java 代码位于一个文件中,而 XML 配置采用独立的配置文件,大多数配置信息在程序开发完成后都不会调整,如果配置信息和 Java 代码放在一起,有助于增强程序的内聚性。而采用独立的 XML 配置文件,程序员在编写一个功能时,往往需要在程序文件和配置文件中不停切换,这种思维上的不连贯会降低开发效率。
常用注解总结
1、Hibernate框架的
Hibernate的注解主要用在持久化类那一块:
@Entity
指定当前类是实体类。
@Entity
public class User() {
private Integer id;
private String name;
}12345
@Table
指定实体类和数据库表之间的对应关系。
属性:
name:指定数据库表的名称
@Entity
@Table(name="t_user")
public class User() {
private Integer id;
private String name;
}123456
@Id
指定当前字段是主键。
@Entity
@Table(name="t_user")
public class User() {
@Id
private Integer id;
private String name;
}1234567
@GeneratedValue
指定主键的生成方式。
属性:
strategy :指定主键生成策略。
JPA 提供的四种标准用法为 TABLE,SEQUENCE,IDENTITY,AUTO。
@Entity
@Table(name="t_user")
public class User() {
@Id
@GeneratedValue(strategy = IDENTITY)
private Integer id;
private String name;
}12345678
@Column
指定实体类属性和数据库表字段之间的对应关系
属性:
name:指定数据库表的列名称。
unique:是否唯一
nullable:是否可以为空
inserttable:是否可以插入
updateable:是否可以更新
@Entity
@Table(name="t_user")
public class User() {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "user_id")
private Integer id;
@Column(name = "user_name")
private String name;
}1234567891011
@Temporal
设置日期时间
方式一:@Temporal(TemporalType.DATE)映射为日期 // birthday date (只有日期)
方式二:@Temporal(TemporalType.TIME)映射为日期 // birthday time (是有时间)
方式三:@Temporal(TemporalType.TIMESTAMP)映射为日期 //birthday datetime (日期+时间)
@Temporal(TemporalType.DATE)
private Date birthday; 123456789
@Lob 作用:设置大数据类型
方式一:
@Lob
private String text; //text longtext
方式二:
@Lob
private byte[] image; // image longblob 1234567
@Enumerated 作用:设置枚举类型
方式一:
/** 保存字符串到数据库 */
@Enumerated(EnumType.STRING)
private Role role;
方式二:
/** 保存整数到数据库 */
@Enumerated(EnumType.ORDINAL)
private Role role;
上面定义的枚举:Role
/** 角色 */
public enum Role {
游客, 会员, 管理员
}
使用:
User user = new User();
user.setRole(Role.管理员); 12345678910111213141516171819
@Transient 作用:修饰的字段不会被持久化
@Transient
private String temp;
这样也可以:
private transient String temp;1234
一对多涉及的注解:
@OneToMany:
作用:建立一对多的关系映射
属性:
targetEntityClass:指定多的多方的类的字节码
mappedBy:指定从表实体类中引用主表对象的名称。
cascade:指定要使用的级联操作
fetch:指定是否采用延迟加载
orphanRemoval:是否使用孤儿删除
@ManyToOne
作用:建立多对一的关系
属性:
targetEntityClass:指定一的一方实体类字节码
cascade:指定要使用的级联操作
fetch:指定是否采用延迟加载
optional:关联是否可选。如果设置为false,则必须始终存在非空关系。
@JoinColumn
作用:用于定义主键字段和外键字段的对应关系。
属性:
name:指定外键字段的名称
referencedColumnName:指定引用主表的主键字段名称
unique:是否唯一。默认值不唯一
nullable:是否允许为空。默认值允许。
insertable:是否允许插入。默认值允许。
updatable:是否允许更新。默认值允许。
columnDefinition:列的定义信息。
多对多涉及的注解:
@ManyToMany
作用:用于映射多对多关系
属性:
cascade:配置级联操作。
fetch:配置是否采用延迟加载。
targetEntity:配置目标的实体类。映射多对多的时候不用写。
@JoinTable
作用:针对中间表的配置
属性:
nam:配置中间表的名称
joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段 inverseJoinColumn:中间表的外键字段关联对方表的主键字段
@JoinColumn
作用:用于定义主键字段和外键字段的对应关系。
属性:
name:指定外键字段的名称
referencedColumnName:指定引用主表的主键字段名称
unique:是否唯一。默认值不唯一
nullable:是否允许为空。默认值允许。
insertable:是否允许插入。默认值允许。
updatable:是否允许更新。默认值允许。
columnDefinition:列的定义信息。
2、Struts2框架的
@NameSpace
出现的位置: 它只能出现在 package 上或者 Action 类上。 一般情况下都是写在 Action 类上。
作用: 指定当前 Action 中所有动作方法的名称空间。
属性:
value: 指定名称空间的名称。写法和 xml 配置时一致。 不指定的话,默认名称空间是""。
@ParentPackage
出现的位置: 它只能出现在 package 上或者 Action 类上。 一般情况下都是写在 Action 类上。
作用: 指定当前动作类所在包的父包。由于我们已经是在类中配置了,所以无需在指定包名了。
属性:
value: 指定父包的名称。
@Action
出现的位置: 它只能出现在 Action 类上或者动作方法上。 一般情况下都是写在动作方法上。
作用: 指定当前动作方法的动作名称。 也就是 xml 配置时 action 标签的 name 属性。
属性:
value: 指定动作名称。
results[]: 它是一个数组,数据类型是注解。用于指定结果视图。此属性可以没有,当没有该属性时,表示不返回任何结果视图。即使用 response 输出响应正文。
interceptorRefs[]: 它是一个数组,数据类型是注解。用于指定引用的拦截器。
@Result
出现的位置: 它可以出现在动作类上,也可以出现在 Action 注解中。
作用: 出现在类上,表示当前动作类中的所有动作方法都可以用此视图。出现在 Action 注解中,表示当前 Action 可用此视图。
属性:
name: 指定逻辑结果视图名称。
type: 指定前往视图的方式。 例如:请求转发,重定向,重定向到另外的动作。
location: 指定前往的地址。可以是一个页面,也可以是一个动作。
@Results
出现的位置: 它可以出现在动作类上,也可以出现在 Action 注解中。
作用: 用于配置多个结果视图。
属性:
value: 它是一个数组,数据类型是 result 注解。
@InterceptorRef
出现的位置: 它可以出现在动作类上或者 Action 注解中。
作用: 用于配置要引用的拦截器或者拦截器栈
属性:
value: 用于指定拦截器或者拦截器栈
3、Spring框架的
1、IOC的注解
@Component :创建对象
@Controller
把视图层类交给Spring管理
@Controller
public class UserAction() {
}1234
@Service
把业务层类交给Spring管理
@Service
public class UserService() {
}1234
@Repository
把持久层类交给Spring管理
@Repository
public class UserDao() {
}1234
@Autowired
根据类型自动注入对象
@Autowired
private UserDao userDao;12
@Qualifier
与上面的Autowired一起用,目的根据id获取对象
//例:把持久化层交给Spring管理,并在业务层通过id注入持久化层对象
@Repository("userDao")
public class UserDao() {}
@Service
public class UserService() {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
}12345678910
@Resource
可以根据类型注入,也可以根据id装配,name属性就是bean的id
@Resource(name="userDao")
private UserDao userDao;12
@Value
注入基本类型和字符串类型
@Scope
单例与多例的配置,默认是单例
singleton(单例);prototype(多例);request session
//例:Action是多例的,所以应配置对应的属性,而dao层是单例的,不用配置
@Controller
@Scope(value="prototype")
public class UserAction() {
}
@Repository
public class UserDao() {
}12345678910111213
@Configuration :
定义配置类,用于替换spring中的xml文件的
@Configuration
public class SpringConfiguration {
}
@ComponentScan:
开启注解扫描
@Configuration
//@ComponentScan(basePackages={"cn"})
//@ComponentScan(value={"cn"})
@ComponentScan({"cn"})//value:指定扫描的包【推荐,因为可以不写】
public class SpringConfiguration {
}12345678
@PropertySource
指定的配置文件
@Configuration
@PropertySource(value="classpath:/config/jdbc.properties")
public class SpringConfiguration {
/**
* 告诉spring框架开启el表达式
* 在4.3版本以前都需要这个占位符类
* 在4.3版本之后以下代码可以省略不写
*/
@Bean
public PropertySourcesPlaceholderConfigurer createPSPC(){
return new PropertySourcesPlaceholderConfigurer();
}
}1234567891011121314
@Bean
用在方法上面,创建对象的,根据方法的返回类型
@Component
public class JdbcConfig {
@Bean(name="dataSource")//相当于:<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource" />
public DataSource createDataSource(){
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
try {
comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
}
comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/springIOC");
comboPooledDataSource.setUser("root");
comboPooledDataSource.setPassword("root");
return comboPooledDataSource;
}
@Bean(name="queryRunner")
public QueryRunner createQr(@Qualifier(value="dataSource") DataSource dataSource){
return new QueryRunner(dataSource);
}
}123456789101112131415161718192021
@Import
导入其他的配置类,交给Spring管理
@Configuration
@Import(value={JdbcConfig.class})
public class SpringConfiguration {
}1234
2、AOP的常用注解
AOP : 全称是Aspect Oriented Programming 即: 面向切面编程
需要在Spring的主配置文件中添加以下标签。开启aop注解的支持
<aop:aspectj-autoproxy/>
@Aspect
作用:把当前类声明为切面类。
@Aspect //声明为切面类
public class MyLogger {
}123
@Before
作用:把当前方法看成是前置通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@Aspect //声明为切面类
public class MyLogger {
//前置通知
@Before("pt1()")
public void beforePrintLog(){
System.out.println("前置通知:打印日志了......");
}
}12345678
@AfterReturning
作用:把当前方法看成是后置通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@Aspect //声明为切面类
public class MyLogger {
//后置通知
@AfterReturning("pt1()")
public void afterRetunningPrintLog(){
System.out.println("后置通知:打印日志了......");
}
}12345678
@AfterThrowing
作用:把当前方法看成是异常通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@Aspect //声明为切面类
public class MyLogger {
//异常通知
@AfterThrowing("pt1()")
public void afterThrowingPrintLog(){
System.out.println("异常通知:打印日志了......");
}
}12345678
@After
作用:把当前方法看成是最终通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@Aspect //声明为切面类
public class MyLogger {
//最终通知
@After("pt1()")
public void afterPrintLog(){
System.out.println("最终通知:打印日志了......");
}
}12345678
@Around
作用:把当前方法看成是环绕通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@Pointcut
作用:指定切入点表达式
属性:
value:指定表达式的内容
/**
* 切入点
*/
@Pointcut("execution(public void cn.service.impl.CustomerServiceImpl.saveCustomer())")
public void pt1(){}
/**
* 环绕通知:
* 是spring提供给我们的手动控制代码执行的通知,
* 方法中需要手动控制方法执行
*
* 参数中需要一个接口:Spring注入的,了解
* ProcedingJoinPoint
*/
@Around("pt1()")
public Object around(ProceedingJoinPoint pjp){
//System.out.println("最终通知:打印日志......");
Object[] obj = pjp.getArgs();//参数
//返回值
Object rtValue = null;
//手动调用方法
try {
//前置通知
System.out.println("前:打印日志");
pjp.proceed(obj);
//后置通知
System.out.println("后:打印日志");
} catch (Throwable e) {
//异常通知
System.out.println("异:打印日志");
e.printStackTrace();
}finally{
//最终通知
System.out.println("终:打印日志");
}
return rtValue;
}123456789101112131415161718192021222324252627282930313233343536
3、事务的注解
@Transactiona
声明在类上是表示全局事务,声明在方法上表示局部事务,局部事务会覆盖全局事务,默认属性是传播事务,非只读
@Transactional(readOnly=true)
public class AccountServiceImpl implements IAccountService {
public Account findAccountById(Integer id) {
return ad.findAccountById(id);
}
}1234567
@EnableTransactionManagement
例1
1.导入jar包,ssh的jar包一共是38个,此时还需要多加一个包,就是struts的注解插件jar。
2.在web.xml文件中配置struts filter 和spring 的listener。代码如下:
<!– spring 监听器 –>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.编写jsp页面
<s:form action=”addBook” namespace=”/” method=”post” theme=”simple”>
书名 <s:textfield name=”name”/> <br/>
作者 <s:textfield name=”author” /> <br/>
<s:submit value=”添加图书”></s:submit>
</s:form>
4.利用struts注解编写action
@ParentPackage(value = “struts-default”)
@Namespace(“/”)
public class BookAction extends ActionSupport implements ModelDriven<Book>{
//模型驱动
public Book book = new Book();
public void setBook(Book book) {
this.book = book;
}
@Override
public Book getModel() {
return book;
}
@Override
@Action(value=”addBook”,results={@Result(name=”success”,location=”/success.jsp”)})
public String execute() throws Exception {
return SUCCESS;
}
}
5.使用spring注解注入service,DAO
action:
@ParentPackage(value = “struts-default”)
@Namespace(“/”)
@Controller
@Scope(“prototype”)
public class BookAction extends ActionSupport implements ModelDriven<Book>{
//模型驱动
public Book book = new Book();
public void setBook(Book book) {
this.book = book;
}
@Override
public Book getModel() {
return book;
}
@Autowired
@Qualifier(“bookService”)
private BookService bookService;
@Override
@Action(value=”addBook”,results={@Result(name=”success”,location=”/success.jsp”)})
public String execute() throws Exception {
bookService.save(book);
return SUCCESS;
}
service:
@Service(“bookService”)
@Transactional
public class BookService {
@Autowired
@Qualifier(“bookDAO”)
private BookDAO bookDAO;
public void save(Book book) {
bookDAO.save(book);
}
}
6.DAO完成数据操作,首先要有hibernateTemplate,通过spring注解注入
@Repository(“bookDAO”)
public class BookDAO {
@Autowired
@Qualifier(“hibernateTemplate”)
private HibernateTemplate hibernateTemplate;
public void save(Book book) {
this.hibernateTemplate.save(book);
}
7.实体类,不再需要hbm.xml文件
@Entity
@Table(name = “book”)
public class Book {
@Id
private int id;
@Column(name=”name”)
private String name;
@Column(name=”author”)
private String author;
8.applicationContext.xml文件
<!– 自动扫描 –>
<context:component-scan base-package=”cn.yuzhi”></context:component-scan>
<!– 注解注入 –>
<context:annotation-config></context:annotation-config>
<!– 引入外部属性文件 –>
<context:property-placeholder location=”classpath:jdbc.properties”/>
<property name=”password” value=”${jdbc.password}”></property>
</bean>
<!– 定义Bean : SessionFactory –>
<bean id=”sessionFactory” class=”org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>
<!– 将连接池注入到SessionFactory –>
<property name=”dataSource” ref=”dataSource”></property>
<!– 配置hibernate常用属性 –>
<property name=”hibernateProperties”>
<props>
<prop key=”hibernate.dialect”>org.hibernate.dialect.MySQLDialect</prop>
<prop key=”hibernate.show_sql”>true</prop>
<prop key=”hibernate.format_sql”>true</prop>
<prop key=”hibernate.hbm2ddl.auto”>update</prop>
</props>
</property>
<!– 引用注解类 ,不再引用hbm文件–>
<property name=”packagesToScan”>
<list>
<value>cn.yuzhi.domain</value>
</list>
</property>
</bean>
<bean id=”hibernateTemplate” class=”org.springframework.orm.hibernate3.HibernateTemplate”>
<property name=”sessionFactory” ref=”sessionFactory”></property>
</bean>
<!– spring 采用声明式事务管理 –>
<bean id=”transactionManager” class=”org.springframework.orm.hibernate3.HibernateTransactionManager”>
<property name=”sessionFactory” ref=”sessionFactory”></property>
</bean>
<tx:annotation-driven transaction-manager=”transactionManager”/>