11_用@Resource注解完成属性装配 & 12_编码剖析@Resource注解的实现原理
(2009-12-30 11:20:23)
编码解析实现原理日后补充
使用Field注入(用于注解方式)
手工注入依赖对象,有两种方式。
1、在配置文件中使用setter方法注入
2、使用@Autowired或@Resource注解方式,需要在配置文件中配置如下信息:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
</beans>
注解在spring安装目录的lib/j2ee/common-annotations.jar
@Resource 默认按照名称注入,当找不到名称匹配的bean才会按照类型注入。(推荐使用)
@Autowired默认按照类型注入。
注解注入代码量少,推荐使用。
一个完整的例子如下
1、beans.xml文件内容如下
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config/> <bean id="personDao" class="com.nbchina.service.impl.PersonDaoBean"/> <bean id="personService" class="com.nbchina.service.impl.PersonServiceBean"/> </beans>
2、PersonServiceBean.java 文件
package com.nbchina.service.impl; import javax.annotation.Resource; import com.nbchina.service.PersonDao; import com.nbchina.service.PersonService; public class PersonServiceBean implements PersonService { @Resource private PersonDao personDao; public void save(){ personDao.add(); } }
3、SpringTest.java文件
package junit.test; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.nbchina.service.PersonService; public class SpringTest { @BeforeClass public static void setUpBeforeClass() throws Exception { } @Test public void instanceSpring(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); PersonService personService=(PersonService) ctx.getBean("personService"); personService.save(); } }
13_@Autowire注解与自动装配
(2009-12-30 13:55:23)
Autowired注解是按类型装配依赖对象,默认情况下要求依赖对象必须存在。如果允许null值,可以设置它required属性为false.
若想使用按名称装配,则可以结合@Qualifier
例如:
@Autowired @Qualifier("personDao") private PersonDao personDao;
@Autowired(required=false) private PersonDao personDao;
自动装配形式。了解他,但不推荐使用。
<bean id="" class="" autowire="byType"/>
autowire属性如下:
byType:按类型装配
byName:按名称装配
constructor:与byType方式类似,不同之处在于它应用于构造器函数。
autodetect:通过自省机制来决定是使用constructor还是byType方式进行自动装配。若发现默认的构造器,则使用byType.
14_让Spring自动扫描和管理Bean
(2009-12-30 15:33:23)
spring2.5为引入了组件自动扫描机制,可以在类路径下寻找标注了@Component、@Service、@Controller、@Repository注解的类,把这些类纳入spring容器中管理。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.nbchina"/>
</beans>
@Service用于标注业务层组件。 @Controller用于标注控制层组件,如struts中的action。
@Repository用于标注数据访问组件,即DAO组件。 @Component泛指组件,当组件不好归类的时候,可以用这个注解进行标注。
@Service("name") 可以标注名称
@Scope("prototype") 指定作用域
例如
1、
@Service("name") @Scope("prototype") public class PersonServiceBean implements PersonService { private PersonDao personDao; public void save(){ personDao.add(); } }
2、
@PostConstruct 指定初始化方法 @Service("name") @Scope("prototype") public class PersonServiceBean implements PersonService { private PersonDao personDao; @PostConstruct public void init(){ System.out.println("初始化"); } public void save(){ personDao.add(); } }
3、
@PreDestroy 指定关闭资源方法 @Service("name") public class PersonServiceBean implements PersonService { private PersonDao personDao; @PreDestroy public void destory(){ System.out.println("关闭资源"); } public void save(){ personDao.add(); } }
15_使用JDK中的Proxy技术实现AOP功能&16_使用CGLIB实现AOP功能与AOP概念解释
(2009-12-31 10:01:07)
AOP中的概念
Aspect(切面) 指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样。类是对物体的特征的抽象,而切面是横切性关注点的抽象。
Joinpoint(连结点) 指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连结点,实际上joinpoint还可以是field或类构造器。
Pointcut(切入点) 指我们要对那些joinpoint连结点进行拦截的定义。
Advice(通知) 指拦截到joinpoint之后所要做的事情就是通知。分为前置通知,后置通知,例外通知,最终通知,环绕通知。
Target(目标对象) 代理的目标对象
Weave(织入) 指将Aspects切面应用到target目标对象并导致proxy代理对象创建的过程。
Introduction(引入) 再不修改类代码的前提下,Introduction引入可以在运行期为类动态的添加一些方法或者field。
首先认识一下,不使用框架实现AOP
JDKProxyFactory.java 和 CGlibProxyFactory.java
区别就是一个能实现有接口的类。一个可以实现没有接口的类。
实际例子,运用在权限判断
1、PersonServiceBean.java
package com.nbchina.service.impl; import com.nbchina.service.PersonService; public class PersonServiceBean implements PersonService { private String user = null; public PersonServiceBean(){ } public PersonServiceBean(String user){ this.user=user; } public String getPersonName(Integer personid) { System.out.println("我是getPersonName()方法"); return "xxx"; } public void save(String name) { System.out.println("我是save()方法"); } public void update(String name, Integer personid) { System.out.println("我是update()方法"); } public String getUser() { return user; } }
重构抽取接口。
2、AOPTest.java
package junit.test; import org.junit.BeforeClass; import org.junit.Test; import com.nbchina.aop.CGlibProxyFactory; import com.nbchina.aop.JDKProxyFactory; import com.nbchina.service.PersonService; import com.nbchina.service.impl.PersonServiceBean; public class AOPTest { @BeforeClass public static void setUpBeforeClass() throws Exception { } @Test public void proxyTest(){ JDKProxyFactory factory = new JDKProxyFactory(); PersonService service = (PersonService)factory.createProxyIntance(new PersonServiceBean("ddd")); service.save("999"); } @Test public void proxyTest2(){ CGlibProxyFactory factory = new CGlibProxyFactory(); PersonServiceBean service = (PersonServiceBean)factory.createProxyIntance(new PersonServiceBean("ddd")); service.save("999"); } }
3、JDKProxyFactory.java
package com.nbchina.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.nbchina.service.impl.*; public class JDKProxyFactory implements InvocationHandler{ private Object targetObject; public Object createProxyIntance(Object targetObject){ this.targetObject = targetObject; return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), this.targetObject.getClass().getInterfaces(),this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ PersonServiceBean bean = (PersonServiceBean) this.targetObject; Object result = null; if(bean.getUser()!=null){ result = method.invoke(targetObject, args); } return result; } }
4、CGlibProxyFactory.java
package com.nbchina.aop; import java.lang.reflect.Method; import com.nbchina.service.impl.PersonServiceBean; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGlibProxyFactory implements MethodInterceptor { private Object targetObject; public Object createProxyIntance(Object targetObject){ this.targetObject = targetObject; Enhancer enhancer= new Enhancer(); enhancer.setSuperclass(this.targetObject.getClass()); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { PersonServiceBean bean = (PersonServiceBean) this.targetObject; Object result = null; if(bean.getUser()!=null){ //advice() 前置通知 try { result = methodProxy.invoke(targetObject, args); //afteradvice() 后置通知 } catch (RuntimeException e) { //exceptionadvice() 例外通知 }finally{ //finallyadvice() 最终通知 } } return null; } }
17_Spring的注解方式实现AOP入门&18_Spring的注解方式实现AOP的细节
&19_Spring配置文件实现AOP&20_aspectj的切入点语法定义细节
(2009-12-31 15:01:07)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy/><!-- 支持注解方式 -->
</beans>
AOP一般运用于权限系统或运行期监控
spring提供了两种切面使用方式,实际工作中我们可以选用其中一种:
1、基于XML配置方式进行AOP开发。
2、基于注解方式进行AOP开发。
@Pointcut("execution(* com.nbchina.service..*.*(..))")
第一个*,代表返回值类型。
第二个..,代表对子包下面的类拦截。
第三个* 代表哪个类。
第四个* 代表哪个方法。
第五个(..) 代表方法参数随意。
例如
@Pointcut("execution(!void com.nbchina.service..*.*(..))")
拦截非void返回类型
完整例子,新建一个java项目
1、PersonServiceBean.java
package com.nbchina.service.impl; import com.nbchina.service.PersonService; public class PersonServiceBean implements PersonService { public String getPersonName(Integer id){ System.out.println("我是getPersonName方法"); return "xxx"; } public void save(String name){ System.out.println("我是save方法"); } public void update(String name, Integer id){ System.out.println("我是update方法"); } }
重构抽取接口
2、MyInterceptor.java
package com.nbchina.service; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; /** *切面 */ <!--若基于xml配置方式,去掉@Aspect--> @Aspect public class MyInterceptor { @Pointcut("execution (* com.nbchina.service.impl.PersonServiceBean.*(..))") private void anyMethod(){} //声明一个切入点 // @Before("anyMethod()") //定义前置通知 // public void doAccessCheck(){ // System.out.println("前置通知"); // // } @Before("anyMethod() && args(name)") //定义前置通知,获取 public void doAccessCheck(String name){ System.out.println("前置通知"+ name); } // @AfterReturning("anyMethod()") // public void doAfterReturning(){ // System.out.println("后置通知"); // } @AfterReturning(pointcut="anyMethod()",returning="result") public void doAfterReturning(String result){ System.out.println("后置通知"+result); } @After("anyMethod()") public void doAfter(){ System.out.println("最终通知"); } @AfterThrowing("anyMethod()") public void doAfterThrowing(){ System.out.println("例外通知"); } @Around("anyMethod()") //环绕通知 public Object doBasicProfilling(ProceedingJoinPoint pjp) throws Throwable{ //特别适合做权限 //if(){ System.out.println("进入方法"); Object result = pjp.proceed(); System.out.println("退出方法"); //} return result; } }
3、beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <aop:aspectj-autoproxy/> <!--基于注解方式 <bean id="myInterceptor" class="com.nbchina.service.MyInterceptor"></bean> <bean id="personService" class="com.nbchina.service.impl.PersonServiceBean"></bean> --> <!--基于xml配置方式 <bean id="personService" class="com.nbchina.service.impl.PersonServiceBean"></bean> <bean id="aspetbean" class="com.nbchina.service.MyInterceptor"></bean> <aop:config> <aop:aspect id="asp" ref="aspetbean"> <aop:pointcut id="mycut" expression="execution(* com.nbchina.service.impl.PersonServiceBean.*(..))" /> <!-- 拦截非void类型的。!非的意思 <aop:pointcut id="mycut" expression="execution(!void com.nbchina.service.impl.PersonServiceBean.*(..))" /> --> <aop:before pointcut-ref="mycut" method="doAccessCheck"/> <aop:after-returning pointcut-ref="mycut" method="doAfterReturuning"/> <aop:after-throwing pointcut-ref="mycut" method="doAfterThrowing"/> <aop:after pointcut-ref="mycut" method="doAfter"/> <aop:around pointcut-ref="mycut" method="doBasicProfiling"/> </aop:aspect> </aop:config> --> </beans>
4、SpringAOPTest.java
package junit.test; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.nbchina.service.PersonService; public class SpringAOPTest { @BeforeClass public static void setUpBeforeClass() throws Exception { } @Test public void interceptorTest(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); PersonService personService=(PersonService) ctx.getBean("personService"); personService.save("xxx"); personService.getPersonName(2); } }